Jeremy
Jeremy

Reputation: 77

Importing C++ custom library functions into C#

I currently have a large C++ library that I need to incorporate into a C# project. I was successful in using DllImport to get access to some functions from my library, like this:

[DllImport("MyLib.dll")]
public static extern int SampleFunction(string param);

However, I can't seem to figure out how to make it work for functions that either have a parameter or return type that is not defined within the dll itself (i.e., the code in the dll imports it from another file), such as this example function that takes in a list:

[DllImport("MyLib.dll")]
public static extern std::vector<MyClass> MyFunction(string param);

For std library functions, I know I can get the dll and import that in, but what about other classes like MyClass in the above example? Do I need to create a managed wrapper class in C++ for each of these classes, or is there another way to do this?

Upvotes: 2

Views: 1396

Answers (2)

David Heffernan
David Heffernan

Reputation: 612794

std::vector<MyClass>, or indeed any unmanaged C++ class, cannot be used for interop to C#. Indeed, even if you wished to consume this function from another unmanaged C++ module you'd have to make sure that you were using the same compiler and dynamic runtime as the DLL which exported the function.

You'll need to find some other way to implement this functionality. There are lots of different ways to do that.

  • You could expose a p/invoke interface to the functionality. That would likely involve declaring a struct to represent the data of your class, and serializing to and from that struct.
  • You might consider a COM interface but it won't offer great advantages over p/invoke. You'd still need to serialize your class.
  • A C++/CLI wrapper would be yet another option. You'd wrap the unmanaged class with a managed C++/CLI class, and then consume that from the C#.

Upvotes: 1

Jun
Jun

Reputation: 804

If you need a custom class from a native lib, you'll probably need to export a type library or use managed C++ to write a wrapper. What you're effectively trying to do is marshal a piece of memory from native to managed and now have to deal with how the data type is marshaled.

If at all possible, I would actually recommend trying to do away with the marshaling as when it works it's fine, but when it breaks, it can be rage inducing to debug.

Regardless, I'm actually not sure if anything in the STL can be marshaled. At the very least, I have never seen it done. More times, I've had to do a conversion like so: How can I marshall a vector<int> from a C++ dll to a C# application?

If you want to marshal an actual class, the standard way I've done it up until now is through a type library: Import TLB into C#

Or by linking a native lib into a managed C++ class and then referencing the managed C++ dll into the C# project as a shim.

Beyond that, if you can convert the class to strict C-style functions and pass a struct around, that could allow you to just use pinvoke, this is no different from simply exporting a bunch of helper functions except you can marshal a struct representation back and forth: Marshal C++ struct array into C#

Upvotes: 1

Related Questions