Question

I can call C++ wrapper class from C# via

[DllImport("SomeDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void M();

Where in the C++ code I have

extern "C" { __declspec(dllexport) BSTR GroupTerm(); }
void M() { /* Do Stuff */ }

This works great, however for a number of reasons, I want to include the method M in a class

class SomeClass {
public: 
    void M();
}

I have tried doing

class SomeClass {
public:
   void __declspec(dllexport) M();
}

where

void __declspec(dllexport) SomeClass::M() { /* Do Stuff */ }

But the C# code (using the C# code for import declared above) cannot find the entry point and throws an exception. My question is then, how can I export this method M() [which is a public member of SomeClass for use with interop/pinvoke from C#?

Thanks for your time.

Was it helpful?

Solution

Well there is a few ways, all with different merrits.

One of the more simple is to make a C-wrapper for your C++ class (i'm too lazy to put in the decorations, you should do that yourself).

class SomeClass {
public: 
  void M();
};

void* MakeSomeClass() {return new SomeClass();}
void DestroySomeClassHandle(void* handle) { delete (SomeClass*)handle;}
void M(void* handle) { ((SomeClass*)handle)->M();}

Then you import the C functions as you normally would.

The upside to this is you don't have to do anything you aren't currently familiar with. Many more things (Matlab, Python, ect) have things similar to PInvoke, so this makes your code much more cross-language usable.

The downside is this is super error prone, and you throw away alot of your type safety.

The better way (imho) is to make a C++/CLI wrapper for the class

public ref class ManageSomeClass
{
public:
  ManageSomeClass() {myclass_ = new SomeClass();}
  !ManageSomeClass() { if (myclass) {delete myclass; myclass_ = NULL;} }
  ~ManageSomeClass() { this->!ManageSomeClass(); }
  void M() { myclass_->M();}
private:
  SomeClass* myclass_;
};

I used SomeClass as a pointer to show the destructor-finalizer, but it doesn't need to be a pointer. It could be a full instance. The big thing is that this will be compiled into a .NET class (in a dll) and you can import it into your C# code. Then the call is:

//c# code
ManageSomeClass msc = new ManageSomeClass();
msc.M();

Upside is the flexibility to go from managed to unmanaged like that. The downside is that you are suddenly maintaining another interface. If you have inheritence/polymorphism, your wrappers have to mirror that structure. This is also a nightmare to maintain.

Edit: Another downside is you have to learn C++/CLI, which is (kindof) and extension of C++ and also (kindof) a completely different language.

The final way is through COM interfaces. http://msdn.microsoft.com/en-us/library/aa645736%28v=vs.71%29.aspx. You can use the same COM import calls you use in C++ in C# (with some minor differences) to instantiate and call COM classes. But you need to learn COM (which I've never done) and then implement your class in a COM complaint way. But then you have a COM interface, which can be imported all over Windows.

OTHER TIPS

Assuming the method is static you have a couple of choices:

  1. Use a tool like Dependency Walker to find out the name under which the function is imported. Use the EntryPoint parameter of DllImport to locate it.
  2. Export the function with a .def file. Then you have total control over the exported name.
  3. Wrap the method in a non-member function and export that.

Frankly, option 3 is the one I would select.

When you get around to member functions you'll need to export functions that accept an instance pointer as their first parameter. And you'll likely have to export functions that instantiate objects.

That said, and responding to your comments, other likely better solutions to your problem are:

  1. Early bound COM, or
  2. A C++/CLI wrapper.

Another method (apart from what @MadScienceDreams and @DavidHeffernan said) is to make your C++ code into a Windows Runtime DLL and then it can be used in your C# code. See here for the details and sample: Creating Windows Runtime Components in C++

Excerpt from the link:

article shows how to use C++ to create a Windows Runtime component, which is a DLL that's callable from a Windows Store app that's built by using JavaScript—or C#, Visual Basic, or C++

...

In general, when you code your C++ component, use the regular C++ library and built-in types, except at the abstract binary interface (ABI) boundary where you are passing data to and from code in another .winmd package. There, use Windows Runtime types and the special syntax that Visual C++ supports for creating and manipulating those types. In addition, in your Visual C++ code, use types such as delegate and event to implement events that can be fired from your component and handled in JavaScript, Visual Basic, or C#.

Here is the sample code for "Creating Windows Runtime Components in C++".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top