如何制作一个 PInvoke 友好的原生 API?

Posted

技术标签:

【中文标题】如何制作一个 PInvoke 友好的原生 API?【英文标题】:How to make a PInvoke friendly native-API? 【发布时间】:2010-01-19 07:23:19 【问题描述】:

如何让原生 API 对 PInvoke 友好?

有一些关于如何修改本机程序以与 P/Invoke here 一起使用的提示。但在我编写本机程序之前,我应该注意哪些事项才能使我的程序/库 PInvoke 友好?

使用 C 或 C++ 都可以。


更新: 如果我编写一个 C API,我必须做些什么才能使用 C# 语法进行 P/Invoke-able,如下所示:
[DLLimport("MyDLL.dll")]

是否可以对本机 C++ 代码/库执行相同操作?


制作 P/Invoke 友好的原生 API 的一些技巧的总结/改写: + 参数应该是原生类型(int、char*、float、...) + 参数越少越好 + 如果动态内存被分配并传递给托管代码,请确保创建一个“更清洁”的函数,它也是 p/invoked + 提供示例和/或单元测试来说明如何从 .NET 调用 API + 提供 C++/CLI 包装器

【问题讨论】:

【参考方案1】:

不使用 P/Invoke,如果您自己控制本机库,您可以编写一组 C++/CLI 类来包装本机调用。在许多情况下,这将比使用平台调用执行得更好,并且您可以获得类型正确性的额外好处。例如,如果你有类似下面的某种 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 中完成本机互操作的更优雅的解决方案。

【讨论】:

【参考方案2】:

根据定义,每个本机函数都可以从托管代码中调用/调用。但是为了对 p/invoke 友好,函数应该具有尽可能少的参数,这些参数应该是本机类型(int、char*、float、...)。此外,如果函数在返回给托管代码的某个指针上分配内存,请确保编写其计数器部分以释放指针,因为托管代码无法释放从非托管代码分配的内存。

【讨论】:

"一个函数应该有尽可能少的参数,这些参数应该是本机类型(int,char*,float,...)"我可以把它总结为:->参数应该是本机类型 (int, char*, float, ...) -> 参数越少越好 -> 如果动态内存被分配并传递给托管代码,请确保创建一个“更清洁”的函数,该函数也是 p/invoked跨度> 【参考方案3】:

提供一个从 C# 或 .NET 正确调用它的示例,最好提供一个包含所有方法的 .NET 类

使用 nunit 编写简单的单元测试 这证明您的代码可以正常工作 从.Net调用时会很棒 这样做的方法。

还请记住,可能调用您的代码的 .NET 开发人员不太可能了解 C++,或者不知道不同数据类型的大小等,也不知道这些类型如何映射到 PInvoke 属性。

首先要考虑您希望客户代码的外观,然后设计一个允许它的 API。

【讨论】:

以上是关于如何制作一个 PInvoke 友好的原生 API?的主要内容,如果未能解决你的问题,请参考以下文章

nodejsexpress学习

如何在liferay中制作友好的网址

全新一代API网关,带可视化管理,文档贼友好!

如何制作 Skype 友好的链接(预览图像标签)

如何使用 .htaccess 和 php 制作用户友好的 url

PInvoke - 如何编组'SomeType * []'?