2015-04-08 4 views
0

У меня есть библиотеки DLL с функцией:Как использовать функцию dll extern «C», используя char ** в качестве аргумента в приложении C#?

extern "C" 
int 
doJob(char** buffer); 

Его использование с C++ выглядит следующим образом:

char* buf; 
int status = doJob(&buf); 

Какое определение я должен иметь для этой функции в C#? Как использовать эту функцию в C#?

+2

Google легко приносит много ответов, как [это] (https://msdn.microsoft.com/en-us/library/26thfadc%28v=vs. 110% 29.aspx) ... – pascal

+0

Он может иметь несколько подписей, в зависимости от того, что вы хотите с ним делать. Проблема в том, кто будет писать на 'buffer', вызывающей функции или' doJob'? – xanatos

+0

Главный вопрос заключается не в том, как использовать C dll в C# - с простыми случаями использования. Я знаю, как это сделать: – Sviatoslav

ответ

0

Одним из возможных паттернов:

[DllImport("containsdojob.dll", CallingConvention = CallingConvention.Cdecl)] 
public static extern Int32 doJob(out IntPtr buffer); 

[DllImport("containsdojob.dll", CallingConvention = CallingConvention.Cdecl)] 
public static extern void freeMemory(IntPtr buffer); 

и

IntPtr buffer = IntPtr.Zero; 
string str = null; 

try 
{ 
    doJob(out buffer); 

    if (buffer != IntPtr.Zero) 
    { 
     str = Marshal.PtrToStringAnsi(buffer); 
    } 
} 
finally 
{ 
    if (buffer != IntPtr.Zero) 
    { 
     freeMemory(buffer); 
    } 
} 

Обратите внимание, что вам нужен метод freeMemory, чтобы освободить память, выделенную doJob.

Существуют и другие возможные структуры, например, на основе BSTR и SysAllocString, которые легче реализовать на C# -side (но более сложно реализовать С-сторона)

«Схема» для использования BSTR:

С-сторона:

char *str = "Foo"; // your string 
int len = strlen(str); 
int wslen = MultiByteToWideChar(CP_ACP, 0, str, len, 0, 0); 
BSTR bstr = SysAllocStringLen(NULL, wslen); 
MultiByteToWideChar(CP_ACP, 0, str, len, bstr, wslen); 
// bstr is the returned string 

C# -side:

[DllImport("containsdojob.dll", CallingConvention = CallingConvention.Cdecl)] 
public static extern Int32 doJob([MarshalAs(UnmanagedType.BStr)] out string buffer); 

string str; 
doJob(out str); 

Память автоматически обрабатывается (освобождается) средой CLR.

Если вы используете Visual C++ вы можете даже

char *str = "Foo"; // your string 
_bstr_t bstrt(str); 
BSTR bstr = bstrt.Detach(); 
// bstr is the returned string 

Или C стороны, вы можете использовать один из двух распределителей, которые могут быть освобождены C# -side: LocalAlloc или CoTaskMemAlloc:

char *str = "Foo"; // your string 
char *buf = (char*)LocalAlloc(LMEM_FIXED, strlen(str) + 1); 
// or char *buf = (char*)CoTaskMemAlloc(strlen(str) + 1); 
strcpy(buf, str); 
// buf is the returned string 

Затем вы используете первый пример, но вместо вызова

freeMemory(buffer); 

Вы звоните:

Marshal.FreeHGlobal(buffer); // for LocalAlloc 

или

Marshal.FreeCoTaskMem(buffer); // for CoTaskMemAlloc 
+0

Спасибо! Я сейчас проверю этот метод. – Sviatoslav

+0

Большое спасибо! Ваш ответ помог мне - он работает сейчас! Кстати, «freeMemory» также существует в одной и той же DLL. – Sviatoslav

+0

Я использовал первый метод - с IntPtr. – Sviatoslav

 Смежные вопросы

  • Нет связанных вопросов^_^