Проблема с использованием объявления подписи __declspec (dllexport) из C ++ dll для вызова в C # - PullRequest
0 голосов
/ 24 декабря 2010

Я пытаюсь вызвать метод, который находится в dll C ++, объявленном как __declspec (dllexport) для использования в C #, но я не знаю, как вернуть строковое значение из C ++ и как объявить сигнатуру с помощью DllImport в C #.

C ++ код "VNVAPI.dll"

  __declspec(dllexport) char * GetGpuName(int phyGPUid)
  {
      CNvidia * pInstance = CNvidia::GetInstance();
      char  szName[512]={0};
      pInstance->GetGpuName(phyGPUid,szName,512);
      return szName;
  }

Подпись метода C #:

[DllImport("VNVAPI.dll")]
   public static extern  char GetGpuName(int phyGPUid);

Произошла ошибка:

вызов функции PInvoke 'Ядро! Core.Hardware.IO.NVAPI :: GetGpuName' разбалансировал стек. Это скорее всего потому, что управляемый ПИнвок подпись не соответствует неуправляемой целевая подпись. Проверьте, что соглашение о вызовах и параметры подпись PInvoke соответствует цели неуправляемая подпись.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 24 декабря 2010

Как уже указывалось другими, вам нужно указать соглашение о вызовах C в вашем P / Invoke, а также использовать строку на управляемой стороне для маршалирования завершенного нулем символа *.

Однако вы должны перенастроить подпрограмму C ++, чтобы взять char * в качестве входного параметра вместе с параметром длины буфера. Затем вы пишете в этот буфер в нативный код. Это позволяет избежать текущей проблемы, заключающейся в том, что данные, поскольку у вас есть код, возвращаются из стека, который, конечно, разматывается при возврате функции.

Предложение использовать static сделает эту память глобальной и, таким образом, позволит избежать проблем с перемоткой стека за счет безопасности потоков. Да, это, вероятно, подойдет для этого варианта использования, но это плохая привычка.

0 голосов
/ 24 декабря 2010

Сообщение об ошибке предлагает проверить соглашение о вызовах.Я подозреваю, что функция использует соглашение о вызовах C, которое объясняет несбалансированный стек.Я бы посоветовал вам указать соглашение о вызовах (как предложено @leppi) в атрибуте DllImport.Например:

[DllImport("VNVAPI.dll", CallingConvention=CallingConvention.Cdecl)]

Согласно Образцам строк , возвращаемое значение должно быть string:

static extern string GetGpuName(int phyGPUid);
0 голосов
/ 24 декабря 2010

Сообщение об ошибке может сбить с толку.

Не вдаваясь в подробности, попробуйте это:

static char  szName[512]={0};

Если вы все еще получаете сообщение об ошибке, вам нужно указать соглашение о вызовах в атрибуте DllImport.

Edit:

Также сделайте тип возврата string для объявления метода C #.

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