2014-11-19 3 views
0

Существует много статей о конкретной проблеме с использованием DllImport. Увы, часто я вижу разные ответы на один и тот же вопрос. Например, некоторые говорят, что если функция C++ возвращает aa char * и int * strLen, тогда некоторые говорят, что я должен использовать StringBuilder в своем операторе dllImport, а другие говорят о возврате байта [], некоторые из них имеют оператор marshall в dllImport, некоторые нет. Некоторые ответы кажутся необходимыми из-за старых версий C#/.net.DLLImport C++ функции с char * input as и параметры вывода

Итак, вопрос: если вызов dll из C++ довольно прост, без каких-либо странных соглашений о вызовах или других странных элементов, какими должны быть соответствующие функции DllImport, если у вас есть вывод char * и размер или ввод char * и размер ?

c++ .h 
bool SendString(const char* pSendStr, long strSize); 
bool ReadString(char* pReadStr, long& readStrSize); 

Каковы соответствующие DllImports? замените строку instr и outstr на строку? StringBuilder? символ []? байт[]? Требуется ли какое-либо заявление маршала?

+1

'Const символ *' == '' string' и символ * '' == StringBuilder' (обычно) – leppie

+0

насчет полукокса *** –

ответ

2

Как писал leppie, что вы обычно хотите:

[DllImport(my.dll)] 
static extern bool SendString(string sendString, int stringSize); 
[DllImport(my.dll)] 
static extern bool ReadString(StringBuilder readString, ref int readStringSize); 

Это будет делать автоматическое преобразование в Unicode (и обратно) для вас.

Если вам нужен точный доступ к вашему символу *, вы должны использовать байт []. Таким образом, никакое преобразование не выполняется, и у вас больше контроля над тем, что происходит. Обычно вам это не понадобится. Один случай использования может быть, когда ваш char * может включать символы \ 0.

+1

'long' является Ширина 64 бит в C#. Вы также неправильно обрабатываете второй параметр в 'ReadString'. Это ссылка. –

+0

Вы правы. починил это –

5
bool SendString(const char* pSendStr, long strSize); 

Эта функция проста. Текст отправляется от вызывающего абонента. P/Invoke объявляется так:

[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] 
static extern bool SendString(string SendStr, int Len); 

Обратите внимание, что я предполагаю Cdecl соглашение о вызовах поскольку это по умолчанию для кода C++. А также обратите внимание, что long в C++ на Windows имеет ширину 32 бит. Поэтому он соответствует int в C#.

Когда вы вызываете функцию, вам необходимо передать строку и ее длину. Тем не менее, обычное соглашение предназначено для строк с нулевым завершением, поэтому параметр длины не нужен. Я бы объявить неуправляемую функцию следующим образом:

bool SendString(const char* pSendStr); 

И п/ссылаться, как это:

[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] 
static extern bool SendString(string SendStr); 

Другой функция является немного более сложным. Вы заявили следующее:

bool ReadString(char* pReadStr, long& readStrSize); 

Здесь вызывающий абонент выделяет буфер, который заполняется вызываемым абонентом. Вы можете использовать StringBuilder для текста, и пусть маршалер сделает для вас работу. P/invoke:

[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)] 
static extern bool ReadString(StringBuilder ReadStr, ref int Len); 

Соглашение заключается в том, что вы предоставляете длину предоставленного буфера. В свою очередь, функция позволит вам узнать, сколько символов написано.Вы бы вызвать функцию так:

int len = 256; 
StringBuilder ReadStr = new StringBuilder(len); 
bool succeeded = ReadString(ReadStr, ref len); 
if (succeeded) 
{ 
    string str = ReadStr.ToString(); 
} 
Смежные вопросы