调用从C#获取char **的C dll函数

时间:2013-06-03 07:44:59

标签: c# c

我有一个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(?)

3 个答案:

答案 0 :(得分:1)

通常,您的pinvoke签名将是

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

但:

  • 在'adress'参数中,您可能需要通过[MarshalAs]属性和正确的SizeIndex值来指示与'size'的关系。如果你将'out string'更改为'out char []',那么肯定会是必需的,但是如果你使用字符串,如果你返回的字符串是一个普通的以null结尾的字符串,我认为没有必要
  • 如果函数为address数组分配内存,则可能会遇到一些问题,因为函数的使用将假定调用者必须知道如何释放它...请参阅ie https://stackoverflow.com/a/1932956/717732https://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);