c# - 将 StringBuilder 传递给需要 char 指针的 DLL 函数

标签 c# c++ pointers dllimport

我正在尝试与在 Delphi 中创建的 DLL 库进行交互。在 C++ 中,我完美地完成了这个调用:

for(int y = 1; y <= 12; y++)
{
    char * chanName = (char *) malloc(21); 
    memset(chanName,0,21);
    channelName(y,20,chanName);
    ...
}

channelName 类型定义为 typedef int (CALLBACK* ChannelName)(int,int,char*);

现在我正尝试在 C# 中做同样的事情。我搜索并发现 StringBuilder 通常用作 DLL 函数的字符指针。这是我声明函数的方式:

[DllImport("myDLL.dll")]
public static extern int ChannelName(int x, int y, StringBuilder z);

我是这样调用它的:

for (int x = 0; x < 12; x++)
{
    StringBuilder b = new StringBuilder(100);
    DLLInterface.ChannelName(x+1, b.Length, b);
    Console.WriteLine(b.ToString());
}

这只是让控制台打印出乱码,例如:

☺ §
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9

我记得在 C++ 中遇到过类似的问题,这就是为什么我将 memsetmalloc 的内存设置为 0 的原因。我试图在 C# 中找到一个等价物,但也许而是 StringBuilder 的问题?如果我的问题不是很清楚,我只想将一个字符串传递到我的函数中,让函数填充它,然后打印出来。字符串在 C# 中是不可变的,并且不存在好的指针选项,这就是我尝试 StringBuilder 的原因。

最佳答案

在 .NET 中,字符串(和 StringBuilder)是 16 位 Unicode 字符。我的猜测是您的 native 函数处理 8 位 ASCII 字符。你需要告诉 Marshaller 在编码时如何转换字符。像这样更改您的 DllImport 属性:

[DllImport("myDLL.dll", CharSet=CharSet.Ansi)]
public static extern int ChannelName(int x, int y, [Out] StringBuilder z);

已更新

此外,您还应该在 StringBuilder 上指定 [Out] 属性,以便 Marshaller 仅在出路时编码,而您在传入时不传递任何内容。

再次更新

[In,Out] 属性是多余的(这是默认设置),但是将它放在那里可以明确表示您知道您需要 In 和 Out 复制。

[DllImport("myDLL.dll")]
private static extern int ChannelName(int x, int y, [In,Out] byte[] z);
public static int ChannelName(int x, int y, out string result)
{
    byte[] z = new byte[100];
    int ret = ChannelName(x, y, z);
    result = Encoding.ASCII.GetString(z);
    return ret;
}

再次更新

看起来(命名不当的)“y”参数是传入的 char * 缓冲区的长度,我猜它返回写入缓冲区的字符数。如果是这种情况,我将以更自然的 C# 方式包装此调用:

[DllImport("myDLL.dll")]
private static extern int ChannelName(int x, int y, [In, Out] byte[] z);

public static string ChannelName(int x)
{
    byte[] z = new byte[100];
    int length = ChannelName(x, z.Length, z);
    return Encoding.ASCII.GetString(z, 0, length);
}

关于c# - 将 StringBuilder 传递给需要 char 指针的 DLL 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11508260/

相关文章:

c++ - 集合中的智能指针多态性

c - 如何从函数中的矩阵指针赋予值属性

pointers - 如何使用interface{}将整数作为指针传递给函数

c# - 在C#中播放音频文件

c# - 仅当未在 Json.Net 中明确设置 PropertyName 时才使用 CamelCase?

c# - Listbox.Items.Clear() 在 SelectionChanged 上崩溃

c++ [] with vector< vector<int>>

c++ - WinSock - 获取本地 IP 地址

c++ - 删除使用 new 创建的 2D 或 3D 指针

c# - 使用 JSON.NET 反序列化格式错误的 JSON