微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将 char* C 函数编组到 C#

如何解决将 char* C 函数编组到 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)));
}

输出

xychar    ptuchar
x?J

谢谢!

解决方法

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

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

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

您还有两个选择:

  • 自行编组。确保将其放在 try/finally 中以防万一
[DllImport("Sandbox.dll",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",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);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。