我有一个C dll导出一个看起来像这样的函数:
void GetSectionData(TCHAR name [], char **Address, DWORD * Size)
该函数获取一个名称,并在分配了*Size
个字节后返回Address。以下是如何在C中使用该函数的示例:
char *addr[64]:
DWORD Size[64];
TCHAR name[260];
sprintf( name, "myDll.dll);
GetSectionAddress(name, &addr[index],&Size[index]);
我想在没有unsafe
的C#中使用这个dll函数
我的函数声明应该使用DllImport
属性,但我不知道如何声明参数,主要是Address和Size参数(我假设名称可以声明为StringBuilder
):
[DllImport("myDll.dll")]
public static extern void GetSectionData(?)
答案 0 :(得分:1)
通常,您的pinvoke签名将是
static extern void GetSectionData(string name, out string address, out int size);
但:
[MarshalAs]
属性和正确的SizeIndex值来指示与'size'的关系。如果你将'out string'更改为'out char []',那么肯定会是必需的,但是如果你使用字符串,如果你返回的字符串是一个普通的以null结尾的字符串,我认为没有必要address
数组分配内存,则可能会遇到一些问题,因为函数的使用将假定调用者必须知道如何释放它...请参阅ie https://stackoverflow.com/a/1932956/717732或https://stackoverflow.com/a/12274007/717732 - 主要的问题是有很多方法来分配缓冲区(包括基于堆栈的临时数组......),并且调用者将很难猜测。特别是在p / invoke中使用的编组器,因为它对你的代码一无所知.. 答案 1 :(得分:0)
根据Reflector,.Net Framework在内部执行此操作的方式是将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参数。
答案 2 :(得分:0)
[的DllImport( “将myDll.dll”)] public static extern void GetSectionData(StringBuilder name,ref IntPtr Address,ref int32 Size);