调用从c#中获取char**的C dll函数
本文关键字:dll 函数 char 获取 调用 | 更新日期: 2023-09-27 18:16:44
我有一个C dll,它导出一个函数,看起来像这样:
void GetSectionData(TCHAR name [], char **Address, DWORD * Size)
函数获取一个名称,并在分配了*Size
字节后返回地址。下面是如何在C中使用该函数的示例:
char *addr[64]:
DWORD Size[64];
TCHAR name[260];
sprintf( name, "myDll.dll);
GetSectionAddress(name, &addr[index],&Size[index]);
我想在没有unsafe
的c#中使用这个dll函数。
我的函数声明应该使用DllImport
属性,但我不知道如何声明参数,主要是地址和大小参数(我假设名称可以声明为StringBuilder
):
[DllImport("myDll.dll")]
public static extern void GetSectionData(?)
一般来说,您的pinvoke签名将是
static extern void GetSectionData(string name, out string address, out int size);
但:
- 在' address '参数中,您可能需要通过
[MarshalAs]
属性和适当的SizeIndex值指示与'size'的关系。如果您将'out string'更改为'out char[]',那么肯定需要,但如果您使用字符串并且返回的字符串是正常的null终止字符串,我认为这将是不必要的 - 如果函数为
address
数组分配内存,您可能会遇到一些问题,因为使用该函数将假设调用者必须知道如何释放它。请参阅https://stackoverflow.com/a/1932956/717732或https://stackoverflow.com/a/12274007/717732 -主要问题是有很多方法来分配缓冲区(包括基于堆栈的临时数组…),调用者将很难猜测。特别是在p/invoke中使用的编组器,因为它不了解您的代码。
根据Reflector的说法,. net框架内部实现这一点的方式是将StringBuilder
实例传递给char**参数,而其他(数字)指针通常作为IntPtr
传递。一个很好的例子是FormatMessage
,它具有以下签名:
DWORD WINAPI FormatMessage(
_In_ DWORD dwFlags,
_In_opt_ LPCVOID lpSource,
_In_ DWORD dwMessageId,
_In_ DWORD dwLanguageId,
_Out_ LPTSTR lpBuffer,
_In_ DWORD nSize,
_In_opt_ va_list *Arguments
);
在Microsoft.Win32.SafeNativeMethods
下定义为
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId, StringBuilder lpBuffer, int nSize, IntPtr arguments);
System.ComponentModel.Win32Exception
,调用这个方法,执行
int error = 0; //Error code, for example
StringBuilder lpBuffer = new StringBuilder(0x100);
SafeNativeMethods.FormatMessage(0x3200, NativeMethods.NullHandleRef, error, 0, lpBuffer, lpBuffer.Capacity + 1, IntPtr.Zero)
如果您想提取size参数,您可以定义一个不安全的方法,并实际使用类型int*
作为size参数。
[DllImport("myDll.dll")]GetSectionData(StringBuilder名称,ref IntPtr地址,ref int32大小);