Передача строки C # в неуправляемую DLL-библиотеку C в Windows Mobile - PullRequest
8 голосов
/ 20 октября 2010

У меня есть неуправляемая DLL-библиотека c ++, которую мне нужно вызывать из приложения для Windows Mobile C # .

У меня есть оболочка C #, и она отлично работает на рабочем столе.Я могу вызывать функции DLL из настольной программы на C # и без проблем передавать строки.

Однако, когда я компилирую lib и оболочку для мобильной платформы, я получаю сообщение об ошибке в строках DllImport, в котором говорится, чтоCharSet.ANSI не распознается.Единственные опции, которые мне разрешено писать, это CharSet.Auto и CharSet.Unicode.

Проблема в том, что независимо от этого параметра строки, получаемые в функциях c ++, являются строками широких символов, а необычные char * строки - это то, что они ожидают.

Мы можем использовать wcstombs () для перевода всех строк в начале каждой функции c ++, но я бы не стал изменять библиотеку до такой степени ...

Есть ли способ исправить сортировку между C # и C, которая работает с .NET Compact Framework?

Ответы [ 3 ]

7 голосов
/ 12 ноября 2010

Нет, нет.

Документация Microsoft указывает, что:

[...] .NET Compact Framework * только 1008 *поддерживает Unicode и, следовательно, включает в себя только значение CharSet.Unicode (и CharSet.Auto, равное Unicode), и не поддерживает ни одно из предложений оператора Declare.Это означает, что свойство ExactSpelling также не поддерживается.

В результате, если ваша функция DLL ожидает строку ANSI, вам потребуется выполнить преобразование в DLL или преобразовать строку в массив байтов, используя перегруженный метод GetBytes из ASCIIEncodingкласс , перед вызовом функции, поскольку .NET Compact Framework всегда будет передавать указатель на строку Unicode.[...]

Решение:

Функции в DLL

int MARSHALMOBILEDLL_API testString(const char* value);
const char* MARSHALMOBILEDLL_API testReturnString(const char* value);

Оболочка

[DllImport("marshalMobileDll.dll")]
public static extern int testString(byte[] value);

[DllImport("marshalMobileDll.dll")]
public static extern System.IntPtr testReturnString(byte[] value);

Телефонный код

string s1 = "1234567";
int v = Wrapper.testString( Encoding.ASCII.GetBytes(s1));

string s2 = "abcdef";
IntPtr ps3 = Wrapper.testReturnString(Encoding.ASCII.GetBytes(s2));
string s3 = IntPtrToString(ps3);


private string IntPtrToString(IntPtr intPtr)
{
  string retVal = "";

  byte b = 0;
  int i = 0;
  while ((b = Marshal.ReadByte(intPtr, i++)) != 0)
  {
    retVal += Convert.ToChar(b);
  }
  return retVal;
}
2 голосов
/ 20 октября 2010

Windows CE сильно склонен к Unicode (большинство Win32 API даже не имеют эквивалентов ANSI). Таким образом, CF тоже не очень хорошо работает с ANSI, и ему нужна небольшая «помощь», чтобы сделать это правильно.

Вы можете сообщить маршалеру, что хотите передать данные как однобайтовые значения с нулевым окончанием, используя атрибут MarshalAs ( документы MSDN четко показывают, что он поддерживается в CF) эти строки:

[DllImport("mydll.dll", SetLastError = true)]
public static extern void Foo([MarshalAs(UnmanagedType.LPStr)]string myString);
0 голосов
/ 22 октября 2010

Я считаю этот маршальский компилятор полезным, даже если он немного глючит

...