Как импортировать void * C API в C #? - PullRequest
9 голосов
/ 06 февраля 2009

Учитывая эту декларацию C API, как она будет импортирована в C #?

int _stdcall z4ctyget(CITY_REC *, void *);

Мне удалось продвинуться так далеко:

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

Естественно, в C # "void *" не компилируется.

В некоторых поисках Google указано, что оно должно быть переведено как «объект». Кажется, это должно сработать. Но другие указывают, что «Void * называется указателем на функцию в терминах C / C ++, которая в терминах C # является делегатом». Это не имеет большого смысла здесь, поскольку, что это делегировало бы? Некоторые похожие вызовы для других API, найденные через Googling, используют другие функции в соответствующем API. Но в этом API никакой другой вызов не имеет смысла.

В документации к звонку приведен пример:

z4ctyget(&city, “00000”);

Что, кажется, показывает, что даже статическое значение может быть передано.

Он будет компилироваться с объектом вместо пустоты *. Я не знаю, правильно ли это, и у меня не было возможности проверить это (проблема лицензирования).

Ответы [ 3 ]

14 голосов
/ 06 февраля 2009

Для параметра void * вы можете просто использовать IntPtr

  [DllImport(@"zip4_w32.dll",
        CallingConvention = CallingConvention.StdCall,
        EntryPoint = "z4ctygetSTD",
        ExactSpelling = false)]
    private extern static int z4ctygetSTD(ref CITY_REC args, IntPtr ptr);
1 голос
/ 06 февраля 2009

Вы также можете использовать void *, если отметите свой класс как небезопасный.

Это действительно зависит от того, что API ищет в этом параметре.

Вы можете добавить IntPtr или Object *, чтобы пройти мимо компилятора, но вам все равно придется передавать ему правильные данные при вызове.

0 голосов
/ 07 февраля 2009

Насколько я могу судить, объявление C для z4ctyget:

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

Второй параметр - это 5-символьная строка ANSI, представляющая почтовый индекс, с которого вы хотите начать поиск, или «00000», чтобы начать с начала файла. Итак, ваша декларация должна быть:

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