Reputation: 7876
How to make a native API to be PInvoke friendly?
there are some tips on how to modify native-programs to be used with P/Invoke here. But before I even write a native programs, what are the things I should look out to make my programs/library PInvoke friendly?
using C or C++ are fine.
[DLLimport("MyDLL.dll")]
is it possible to do the same with native C++ code/library?
Upvotes: 6
Views: 875
Reputation: 4953
Instead of using P/Invoke, if you are controlling the native library yourself, you can write a set of C++/CLI classes that wrap the native calls. In many cases, this will perform better than using platform invoke, and you get the added benefit of type correctness. For example, if you have some sort of C API like the following (it doesn't do anything useful, I just added pointers and structs to reinforce the fact that it is native code):
struct SomeStruct {
int a, b;
int* somePtr;
};
int foo(struct SomeStruct* a, int b) {
*a->somePtr = a->a + a->b;
return a->b * *a->somePtr + b;
}
You can create a C++/CLI class to wrap it:
public ref class MyNativeAPI {
private:
SomeStruct* x;
public:
MyNativeAPI() {
x = new SomeStruct;
}
~MyNativeAPI() {
delete x;
}
int Foo(int a) {
pin_ptr<SomeStruct*> ptr = this->x;
return foo(ptr, a);
}
}
Then, you can call this in C#:
MyNativeAPI a = new MyNativeAPI();
if(a.Foo(5) > 5) { ... };
You'll have to read more on C++/CLI to understand the new controls you have over both the managed heap and the native heap, and the caveats to mixing the two (like the pin_ptr
I used above), but overall it's a much more elegant solution to accomplishing native interop in .NET.
Upvotes: 3
Reputation: 51897
Provide an example of correctly calling it from C# or .NET, even better provide a .NET class that wraps all your methods
Writing a simple unit test with nunit that proves your code works correctly when called from .Net would be a great way of doing it.
Also remember that the .NET developers that are likely to be calling your code are unlikely to know much about C++, or don’t know the sizes of different data types etc or how these types map to the PInvoke attributes.
Above all think about how you wish your clients code to look and then design a API that allows it.
Upvotes: 1
Reputation: 1038710
By definition every native function can be p/invoked from managed code. But in order to be p/invoke friendly a function should have as few parameters as possible which should be of native types (int, char*, float, ...). Also if a function allocates memory on some pointer that is returned to managed code, make sure you write its counter part that will free the pointer as managed code cannot free memory allocated from unmanaged code.
Upvotes: 1