0

我有一个导出函数的 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.
我的函数声明应该使用DllImport属性但我不知道如何声明参数,主要是地址和大小参数(我假设名称可以声明为StringBuilder):

[DllImport("myDll.dll")]
public static extern void GetSectionData(?)
4

3 回答 3

1

通常,您的 pinvoke 签名将是

static extern void GetSectionData(string name, out string address, out int size);

但:

  • 在“地址”参数中,您可能需要通过[MarshalAs]属性和正确的 SizeIndex 值指示与“大小”的关系。如果您将“out string”更改为“out char[]”,那么它肯定是必需的,但是如果您使用 string 并且如果您返回的字符串是一个普通的以 null 结尾的字符串,我认为没有必要
  • 如果函数为数组分配内存address,你可能会遇到一些问题,因为函数的使用会假设调用者必须知道如何释放它。请参见https://stackoverflow.com/a/1932956/717732https://stackoverflow.com/a/12274007/717732 - 主要问题是分配缓冲区的方法很多(包括基于堆栈的临时数组..),调用者很难猜测。尤其是 p/invoke 中使用的编组器,因为它对您的代码一无所知..
于 2013-06-03T07:52:09.903 回答
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参数的类型。

于 2013-06-03T08:19:08.647 回答
0

[DllImport("myDll.dll")] public static extern void GetSectionData(StringBuilder name, ref IntPtr Address, ref int32 Size);

于 2013-06-04T14:59:01.080 回答