Маршаллинг в c # (Передача структуры неуправляемому типу) - PullRequest
3 голосов
/ 26 апреля 2009

У меня есть c ++ dll, которая предоставляет следующую функцию

long func(struct name * myname)
{
     strcpy(myname->firstname,"rakesh");
     strcpy(myname->lastname,"agarwal");
     return S_OK;
}

struct name
{
    char firstname[100];
    char lastname[100];
}

Я хочу вызвать эту функцию из приложения C #, поэтому я делаю следующее:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
unsafe public struct name
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=100)]
    public string firstname;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
    public string lastname;
} ;


[DllImport("C++Dll.dll")]
public unsafe static extern long func(name[] myname);

name[] myname = new name[1];
func(myname);

Приложение успешно собирается. При запуске приложения C # .exe успешно вызывается функция func(), и она может успешно заполнять поля внутри библиотеки DLL. Но когда функция возвращается в приложение C #, переменная myname все еще содержит нулевые значения для полей структуры (firstname и lastname).

Пожалуйста, предложите изменения, чтобы я мог заполнить значения полей myname (чтобы после завершения функции func() переменная myname->firstname содержала "rakesh", а myname->lastname содержала "agarwal").

Примечание: StringBuilder нельзя использовать внутри структуры.

Ответы [ 2 ]

7 голосов
/ 26 апреля 2009

Вместо использования массива передайте структуру по ссылке. Для вызова PInvoke ссылка ref будет преобразована в указатель на структуру. Аргумент ref также указывает CLR маршалировать данные в обоих направлениях, исходный код и затем возвращаться обратно.

[DllImport("C++Dll.dll")]
public unsafe static extern long func(ref name myname);

Кроме того, если вы выполняете большую часть взаимодействия, я предлагаю вам обратиться к помощнику по взаимодействию PInvoke ( ссылка ). Этот инструмент автоматически преобразует большинство определений типов C (включая структуры, перечисления, объединения и указатели функций) в соответствующие им типы C # или VB.Net. Это дополнительно преобразует подписи, которые содержат эти типы.

3 голосов
/ 26 апреля 2009

Объявите импорт как public unsafe static extern long func(ref name myname) и назовите его:

name myname = new name();
func(ref myname);

Между прочим, вам, вероятно, не нужны небезопасные объявления в структуре имен или декларации импорта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...