[英]How to make a PInvoke friendly native-API?
如何使本机API成为PInvoke友好的?
有关于如何修改本机程序,以P中使用的一些技巧/调用这里 。 但在我写一个原生程序之前,我应该注意哪些事情让我的程序/库PInvoke友好?
使用C或C ++很好。
[DLLimport("MyDLL.dll")]
是否可以对本机C ++代码/库执行相同的操作?
如果您自己控制本机库,则可以编写一组包装本机调用的C ++ / CLI类,而不是使用P / Invoke。 在许多情况下,这将比使用平台调用更好,并且您还可以获得类型正确性的额外好处。 例如,如果你有某种类似下面的C API(它没有做任何有用的事情,我只是添加了指针和结构来强化它是本机代码的事实):
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;
}
您可以创建一个C ++ / CLI类来包装它:
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);
}
}
然后,您可以在C#中调用它:
MyNativeAPI a = new MyNativeAPI();
if(a.Foo(5) > 5) { ... };
你必须阅读更多关于C ++ / CLI的内容,以了解你对托管堆和本机堆的新控制,以及混合两者的警告(比如我上面使用的pin_ptr
),但总的来说它更多在.NET中实现本机互操作的优雅解决方案。
根据定义,可以从托管代码调用每个本机函数。 但是为了使p / invoke友好,函数应该具有尽可能少的参数,这些参数应该是本机类型(int,char *,float,...)。 此外,如果函数在返回给托管代码的某个指针上分配内存,请确保编写将释放指针的计数器部分,因为托管代码无法释放从非托管代码分配的内存。
提供从C#或.NET正确调用它的示例,甚至更好地提供包装所有方法的.NET类
用nunit编写一个简单的单元测试,证明你的代码在从.Net调用时正常工作将是一个很好的方法。
还要记住,可能调用代码的.NET开发人员不太了解C ++,或者不知道不同数据类型的大小等,或者这些类型如何映射到PInvoke属性。
最重要的是考虑您希望客户代码的外观,然后设计一个允许它的API。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.