ошибка при вызове dll-функции из кода C # - PullRequest
2 голосов
/ 19 марта 2011

Я создал dll в c ++ и хотел вызвать функцию из нее, используя c #.У меня есть ошибка, если функция, которую вызывает программа, возвращает строку. Код Dll:

#include <string>
using namespace std;
#define EXPORT_API extern "C" __declspec(dllexport) 
EXPORT_API  void DllFunc()
{
    MessageBoxA(0,"DDL box", "Yeah!", 0);
}

EXPORT_API  string DllFuncStr()
{
    return "testStr";
}

Код приложения C #:

[DllImport("dllka.dll")]
 static extern void DllFunc();
[DllImport("dllka.dll")]
static extern string DllFuncStr();

 private void btnStart_Click(object sender, RoutedEventArgs e)
 {
     DllFunc();
     string str = DllFuncStr();           
 }

"DllFunc ();"- работает хорошо, но в строке "string str = DllFuncStr ();"у меня была ошибка:

Во время выполнения произошла фатальная ошибка.Адрес ошибки был 0x5e6dceca, в потоке 0x16b0.Код ошибки 0xc0000005.Эта ошибка может быть ошибкой в ​​CLR или в небезопасных или не поддающихся проверке частях пользовательского кода.Распространенными источниками этой ошибки являются ошибки пользовательского маршалинга для COM-взаимодействия или PInvoke, которые могут повредить стек.

Что не так с строковым типом?Как решить эту проблему?

Ответы [ 2 ]

5 голосов
/ 20 марта 2011

Вы не можете маршалировать std :: string из C ++ в C #.Вместо этого либо используйте строку с нулевым символом в конце, маршализованную с помощью StringBuilder, либо верните BSTR.

Подход BSTR довольно прост.Если вы предпочитаете строку с нулевым символом в конце, то поищите в Интернете примеры P / Вызывает из Win32 API, например, GetWindowText ().

Вы экспортируете из C ++ с соглашением о вызовах cdecl, но используете stdcall в коде C #.Вам нужно будет сопоставить их после того, как вы отсортируете тип данных.Неважно, какой вы используете, при условии, что он одинаков на обоих концах.

Вам также нужно будет уточнить тот факт, что ваш код C ++ использует char (8-битное кодирование), а C # использует собственный UTF Windows-16.

Если бы это был я, я бы сделал это с помощью BSTR, как я обрисую в этот ответ на другой вопрос.

3 голосов
/ 20 марта 2011

Как сказал Дэвид, c ++ std :: string и c # string - это разные вещи. Я сделал это следующим образом в моем приложении:

c ++ DLL-код:

EXPORT_API void DllFuncStr(char* sRetText, int nCapacity)
{
  if(!sRetText)
    return;

  std::string sRetTextStr("testStr");

  strcpy_s(sRetText, nCapacity, sRetTextStr.c_str());
  return;
}

c # код приложения:

[DllImport("dllka.dll")]
static extern bool DllFuncStr(StringBuilder sStrBuilder, int nCapacity);

private void btnStart_Click(object sender, RoutedEventArgs e)
{
  StringBuilder strBuilder = new StringBuilder(50);
  DllFuncStr(strBuilder, strBuilder.Capacity);
  string str = strBuilder.ToString();
}

(Спасибо, Ганс, за предложения. Я исправлю эту вещь и в моем приложении)

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