I've been developing some DLL utility projects to avoid having to repeat code throughout other projects, and also for features, algorithms and tests I haven't tried yet. One of those projects is in C++/CLI, language which I'm still learning, so this question may sound stupid. As I have Library Projects in C++/CLI, F# and C#, I use a C# console application to test them. It wasn't working with the C++/CLI Project, so I created a C++/CLI console test project. It never worked, and when I changed the name of the original DLL C++, the references weren't updated. When I (eventually) found out the problem, I changed the .vcxproj file, making the using directives possible, as for one method, but not for the template class Apont<typename T>, which is some kind of interior pointer, but that unlike the .NET type System::IntPtr, uses a value of the type T* instead of void*.
I also found out (from a post in this site) that I must use inside the project what I want to use outside, otherwise that stuff want be emitted in the metadata. So I have a useless static method in a static utility for that purpose:
static void Funcionalidades()
{
int i = 10;
Apont<int> a2 = Apont<int>(i); // stack
Apont<int> ^a3 = gcnew Apont<int>(i); // heap CLR
}
Nonetheless, it doesn't work. Here is my main method in the C++/CLI test project:
int main(array<System::String ^> ^args)
{
int y(10);
Apont<int> a = Apont<int>(y);
Console::ReadKey();
return 0;
}
And below are the errors (I know it can compile with intellisense errors, but I'll show them anyway):
error C2065: 'Apont' : undeclared identifier
error C2062: type 'int' unexpected
IntelliSense: identifier "Apont" is undefined
IntelliSense: type name is not allowed
IntelliSense: expected an expression
Why are these errors here? How can I correct them?
I'd appreciate any answer or reply.
EDIT (clarifications):
- These errors DO NOT occur on the
Funcionalidadesmethod, that is in the DLL project, but on the main method, that is outside the DLL, in the test project. - I'm writing everything in the header file; I mean not every header file has a respective .cpp file, although all headers are included in at least one .cpp file.
- More about
Apont:Apontis a template (because T* is used inside and "indirections on a generic type paremeter are not allowed").Aponthas a copy constructor, soApont<int> a = Apont<int>(someInt)should work;Apont<int> a(someInt)doesn't work;Apontis some kind of interior pointer; and I didn't post the whole code because it isn't relevant, I'd have to translate varibles' names, and it may have errors I can easily fixed by me, but that would only distract you.
NTH EDIT (where 'n' is a number I don't know):
Apont's code you've been complaining about for so long:
template<typename T> public ref class Apont sealed : public IDisposable
{
bool eliminado;
T *pointer;
/*void Dispose(bool tudo)
{
if (!eliminado)
{
if (tudo)
{
~Apont();
}
else
{
!Apont();
}
}
}*/
!Apont() // finalizador: limpa os recursos "unmanaged"
{
delete pointer;
pointer = nullptr;
eliminado = true;
}
public:
Apont(T &valor)
{
pointer = &valor;
eliminado = false;
ErroSeNulo = false;
ErroSeEliminado = true;
}
Apont(T &valor, bool erroSeEliminado, bool erroSeNulo)
{
pointer = &valor;
eliminado = false;
ErroSeEliminado = erroSeEliminado;
ErroSeNulo = erroSeNulo;
}
Apont(Apont<T> %outroApont)
{
this->pointer = &outroApont
}
property bool ErroSeEliminado;
property bool ErroSeNulo;
property T Valor
{
T get()
{
if (pointer != nullptr)
return *pointer;
else if (eliminado && ErroSeEliminado)
throw gcnew ObjectDisposedException("O objeto já foi pelo menos parcialmente eliminadao.");
else if (ErroSeNulo)
throw gcnew NullReferenceException();
else
return 0;
}
}
/*
Apont operator ~(/*T valor* /)
{
// este operador tem de ser declarado fora desta classe
}*/
T operator !(/*Apont apont*/)
{
return Valor;
}
void operator =(Apont<T> outroApont)
{
pointer = outroApont;
ErroSeEliminado = outroApont.ErroSeEliminado;
ErroSeNulo = outroApont.ErroSeNulo;
}
template<typename U> void operator =(Apont<U> outroApont)
{
pointer = safe_cast<T>(outroApont.pointer);
ErroSeEliminado = safe_cast<T>(outroApont.ErroSeEliminado);
ErroSeNulo = safe_cast<T>(outroApont.ErroSeNulo);
}
/*
void operator =(T *&outroPointer)
{
pointer = outroPointer;
}
template<typename U> void operator =(U *&outroPointer)
{
pointer = safe_cast<T>(outroPointer);
}*/
void operator =(T *outroPointer)
{
pointer = outroPointer;
}
template<typename U> void operator =(U *outroPointer)
{
pointer = safe_cast<T>(outroPointer);
}
~Apont() // destruidor: limpa todos os recursos
{
this->!Apont();
}
// Error C2605: 'Dispose': this method is reserved within a managed class
// O código será gerado automaticamente a partir do finalizador e do destrutor
};
template<typename T> Apont<T> operator ~(T &valor)
{
return gcnew Apont<T>(valor);
}
link /dump /exports mydll.dll. Check that the values and functions you expect to be present are actually present in your dll with the link command I mentioned before. Let me know how you get on and I will try and help you to get this resolved.Utilidades.ComNativosis the namespace I get looking at the dll,Apontis not exposed at all, howeverUtilCMMis, perhaps take a look at what differentiates these two classes? (starting point might be: apont is a sealed class, utilscmm is a static class)