繁体   English   中英

编组字符* C function 到 C#

[英]Marshalling char* C function to C#

我试图了解如何通过在托管和非托管代码之间来回传递和修改字符串来编组 char* 类型。 托管到非托管代码似乎可以正常工作,但反之则不行。 IntPtr 适合这种情况吗?

C

EXPORT char* CharTest(char* ptchar, unsigned char* ptuchar)
{
    ptchar[0] = 'x';
    ptchar[1] = 'y';
    printf("%s    %s\n", ptchar, ptuchar);
    return(ptchar);
}

C#

[DllImport("Sandbox.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
extern static IntPtr CharTest(string ptchar, string ptuchar);

static void Main()
{
    string ptchar = "ptchar";
    string ptuchar = "ptuchar";

    Console.WriteLine(Marshal.PtrToStringAnsi(CharTest(ptchar, ptuchar)));
}

Output

xychar    ptuchar
x?J

谢谢!

您可以将导入的 function 的返回类型声明为string

[DllImport("Sandbox.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
extern static string CharTest(string ptchar, string ptuchar);

但是由于您实际上是在返回参数之一,因此您将不得不依靠编组器在复制返回缓冲区之前不释放参数缓冲区。

您还有两个选择:

  • 自己编组。 确保将其放在try/finally中,以防出现异常
[DllImport("Sandbox.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
extern static IntPtr CharTest(IntPtr ptchar, string ptuchar);

static void Main()
{
    string ptchar = "ptchar";
    string ptuchar = "ptuchar";
    IntPtr ptcharPtr = IntPtr.Zero;

    try
    {
        ptcharPtr = Marshal.StringToHGlobalAnsi(ptchar);
        Console.WriteLine(Marshal.PtrToStringAnsi(CharTest(ptcharPtr, ptuchar)));
    }
    finally
    {
        Marshal.FreeHGlobal(ptcharPtr);
    }
}
  • 将参数声明为StringBuilder ,这意味着它将被双向复制。 在这种情况下,您不需要查看返回值,因为它与参数相同。
[DllImport("Sandbox.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
extern static IntPtr CharTest([In, Out] StringBuilder ptchar, string ptuchar);

static void Main()
{
    StringBuilder ptchar = new StringBuilder("ptchar");
    string ptuchar = "ptuchar";

    CharTest(ptchar, ptuchar);
    Console.WriteLine(ptchar);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM