如何将 void * C API 导入 C#?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/521774/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 06:37:58  来源:igfitidea点击:

How to import void * C API into C#?

c#pinvokedllimport

提问by Mike Chess

Given this C API declaration how would it be imported to C#?

鉴于此 C API 声明,它将如何导入到 C#?

int _stdcall z4ctyget(CITY_REC *, void *);

I've been able to get this far:

我已经能够做到这一点:

   [DllImport(@"zip4_w32.dll",
        CallingConvention = CallingConvention.StdCall,
        EntryPoint = "z4ctygetSTD",
        ExactSpelling = false)]
    private extern static int z4ctygetSTD(ref CITY_REC args, void * ptr);

Naturally in C# the "void *" doesn't compile.

当然,在 C# 中,“void *”不会编译。

Some Googling indicates that it should be translated as "object." Which seems like it should work. But others indicate that "Void * is called a function pointer in C/C++ terms which in C# terms is a delegate". That doesn't make a whole lot of sense here as what would it delegate to? Some similar calls for other APIs found through Googling use other functions in the respective API. But in this API no other call would make sense.

一些谷歌搜索表明它应该被翻译为“对象”。这似乎应该有效。但其他人表示“Void * 在 C/C++ 术语中称为函数指针,在 C# 术语中称为委托”。这在这里没有多大意义,因为它会委托给什么?通过谷歌搜索找到的对其他 API 的一些类似调用使用了相应 API 中的其他函数。但是在这个 API 中,没有其他调用是有意义的。

The documentation for the call shows an example:

通话文档显示了一个示例:

z4ctyget(&city, “00000”);

Which seems to show that even a static value could be passed.

这似乎表明甚至可以传递静态值。

It will compile with object in place of the void *. I don't know whether this is right and I haven't had an opportunity to test it (licensing issue).

它将用 object 代替 void * 进行编译。我不知道这是否正确,而且我还没有机会对其进行测试(许可问题)。

采纳答案by JaredPar

For the void* parameter you can just use an IntPtr

对于 void* 参数,您可以只使用 IntPtr

  [DllImport(@"zip4_w32.dll",
        CallingConvention = CallingConvention.StdCall,
        EntryPoint = "z4ctygetSTD",
        ExactSpelling = false)]
    private extern static int z4ctygetSTD(ref CITY_REC args, IntPtr ptr);

回答by VBNight

You can also use void* if you mark your class as unsafe.

如果您将类标记为不安全,您也可以使用 void*。

It really depends on what the API is looking for in that parameter.

这实际上取决于 API 在该参数中查找的内容。

You can add IntPtr or Object* to get past compiler, but you will still need to pass it the correct data when you call it.

您可以添加 IntPtr 或 Object* 以通过编译器,但您仍然需要在调用它时将正确的数据传递给它。

回答by Stephen Martin

As far as I can tell the C declaration of z4ctyget is:

据我所知,z4ctyget 的 C 声明是:

int z4ctyget(CITY_REC *cityrec, char *zipcode);

The second parameter is a 5 character ANSI string representing the zip code at which you want to start your search or "00000" to start at the beginning of the file. So your declaration should be:

第二个参数是一个 5 个字符的 ANSI 字符串,表示您要开始搜索的邮政编码或从文件开头开始的“00000”。所以你的声明应该是:

[DllImport(@"zip4_w32.dll", CharSet = CharSet.Ansi)]
private extern static int z4ctygetSTD(ref CITY_REC args, string zipcode);