Одним из возможных паттернов:
[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
Google легко приносит много ответов, как [это] (https://msdn.microsoft.com/en-us/library/26thfadc%28v=vs. 110% 29.aspx) ... – pascal
Он может иметь несколько подписей, в зависимости от того, что вы хотите с ним делать. Проблема в том, кто будет писать на 'buffer', вызывающей функции или' doJob'? – xanatos
Главный вопрос заключается не в том, как использовать C dll в C# - с простыми случаями использования. Я знаю, как это сделать: – Sviatoslav