How to properly use a forward declared class in c++ cli? - c++-cli

I am getting error code C2512 which is no appropriate default constructor available. However it appears to me that everything should be working so I am a bit confused on how to get this to compile.
Here is the header file code:
namespace MyNamespace
{
ref class ForwadDeclaredClass;
public ref class MyClass
{
public:
MyClass();
// ...
private:
ForwadDeclaredClass^ fc;
}
}
Now in my cpp file I define the forwarded class and try to use it in the constructor for MyClass.
using namespace MyNamespace;
//...
public ref class ForwardDeclaredClass
{
public:
ForwardDeclaredClass()
{
}
}
MyClass::MyClass()
{
// Compiler complains with error code here
fc = gcnew ForwardDeclaredClass();
}
I know I have to be missing something simple but I am just not seeing it. Any help would be appreciated.

At first glance, it looks like your namespaces are off.
In the header file, you're declaring ForwardDeclaredClass and MyClass inside MyNamespace.
In the cpp file, you're using MyNamespace, but the code you're writing isn't inside the namespace.
It looks like you need to enclose most of the contents of the cpp file in a namespace MyNamespace { block.

Related

Property same name as type - can i get rid of the explicit namespace?

This does not compile without explicit namespaces.
namespace A
{
public enum class Foo {};
public interface class Bar
{
public:
property A::Foo Foo
{
virtual A::Foo get();
};
};
} // namespace A
I used the common .NET/C# style to name the type and property identical here. The explicit namespaces are annoying, especially if they are nested/verbose in a real example.
Can i get rid of the explicit namespaces somehow?
Any way to "beautify" this? I tried using/typedef of the enum in the implementation of the property in the .cpp file to get the enum in the surrounding scope. No success.

Referencing generic class in XAML

I have a class C which is derived from a generic class D. I referenced the class C in a XAML file. When I build the app, I get the following error:
The tag 'C' does not exist in XML namespace 'clr-namespace:A.B'
I don't understand is this due to C is derived from a generic class. If I remove the base class, it does not give me any error.
How can I get rid of the error? The IInterfaceForE is injected via Unity, so the app works fine. But I can't get rid of the build error.
Code snippet:
namespace A.B
{
public class C : D<InterfaceForE>
{
public C()
{
}
}
}
// Reference in XAML
xmlns:myns="clr-namespace:A.B"
<myns:C x:Key="KeyForC"/>
// Code snippet after commenting out the base class.
// When I build with this code, there is no build error, but the app wont run.
namespace A.B
{
public class C //: D<InterfaceForE>
{
public C()
{
}
}
}
I had to remove the generic being used to make this work.

System.NullReferenceException when using gcroot

Turns out this error had nothing to do with gcroot - I connected some constructors shoddily and lost the instantiated object on the way.
For the record, all versions of the code below worked after this fix, but adding the simple Wrapper class allows you to use & and * operators on the wrapped object, which gcroot forbids. I am using the version outlined in the third code block below.
I am trying to use some measuring instruments via a .dll, but I am having problems with the implementation. Writing all the code into the main.cpp and using the object like this works fine:
#using "M3D_FP_USB.dll"
int main(){
M3D_FP_USB ^obj = gcnew M3D_FP_USB;
obj->Connect();
...
}
However, when I put it into a class and wrap it with gcroot, I get an "Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of the object" on execution.
class User{
...
public:
User();
gcroot<M3D_FP_USB^> obj;
}
User::User(){
obj = gcnew M3D_FP_USB;
obj->Connect();
...
}
I suspect that the gcroot or it being called inside the unmanaged class might prevent the instruments from accessing the M3D_FP_USB object. I tried adding a managed Wrapper class, and give a handle to the Wrapper object to the User class. That didn't solve the problem, though.
class User{
...
public:
gcroot<Wrapper^> wobj;
}
ref class Wrapper{
...
public:
M3D_FP_USB^ iobj;
...
}
Wrapper::Wrapper(){
iobj = gcnew M3D_FP_USB;
iobj->Connect();
...
}
The new code I have looks like this, but I couldn't test it with the instruments yet. I will update when I get the chance.
Wrapper::Wrapper(M3D_FP_USB^ obj){
iobj = obj;
iobj->Connect();
...
}
int main(){
M3D_FP_USB ^obj = gcnew M3D_FP_USB;
Wrapper Ex(obj);
}
Does the exception also happen if you make the class managed and just declare the handle directly? Like:
ref class User
{
public:
M3D_FP_USB^ obj;
...
};
Though I don't see why it wouldn't work the way you're doing it...

calling a class constructor present in a dll managed C++

I've a class created in a DLL (which uses /clr runtime, ManagedC++) and a constructor defined in that class. Code as follows:
//Following is defined in something.h//
namespace ABC
{
public ref Class XYZ
{
public: int a;
public: XYZ();
};
//In something.cpp, I've the below code to define the constructor of the class created//
#include something.h
namespace ABC
{
XYZ::XYZ()
{
a = 100;
}
}
Above project is built into a DLL
In another project, I try to use the Class XYZ as follows:
#include something.h
using namespace ABC;
//inside main, I've following code
{
ABC::XYZ^ prq = gcnew ABC:XYZ();
prq->a=200;
......
...
}
In this, I get the an error saying -
unresolved token (06000001) ABC.XYZ::.ctor
Could you please help what's the problem here?
The problem is that the linker can't find the definition of the constructor. It is located in another DLL. In a managed project, you solve that by adding a reference to the assembly. Right-click your project, Properties, Common Properties, Framework and References. Click the Add New Reference button. Use the Project tab if the project is located in the same solution. The Browse tab otherwise.
Also note that you now no longer need the .h file anymore. Declarations are imported from the metadata in the assembly.

How to make my class implement from IMyInterface<T>?

I want to port the following code from c# to c++/cli:
class MyClass : IEnumerable<int> { ... }
I've tried
class ref class MyClass : IEnumerable<int>
but it doesn't seem to be working.
C++ has multiple types of inheritance. Don't forget to specify it, e.g.:
ref class MyClass : public IEnumerable<int>
{ };
In C++/CLI, I frequently find myself spelling out the full namespace in interface implementations. E.g.:
ref class MyClass :
public MyCompany::MyProject::MyComponent::IMyInterface
{ };
If your class doesn't actually implement the provided interface, you'll also (of course) get an error. And you'll want to remove the ^ from the class declaration. You're inheriting from an interface, not from a GC Handle to an instance of that interface.
Assuming your code is exactly what you're trying to compile, you have an extra class there. It should be just ref class, and not class ref class. Also, don't forget to translate any C# using statements to C++ using namespace, i.e.: using namespace System::Collections::Generic.