How to import void * C API into C#?

2020-07-06 04:20发布

问题:

Given this C API declaration how would it be imported to 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.

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.

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).

回答1:

For the void* parameter you can just use an IntPtr

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


回答2:

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

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

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.



回答3:

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

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:

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