如何将此字符数组参数从 C 编组为 C# 中的字符串?

How can I marshal this character array parameter from C to a string in C#?

我有以下函数,作为另一个 class 的一部分写在 C:

int example(char *remoteServerName)
{
    if (doSomething(job))
        return getError(job);
    if (job->server != NULL) {
        int length = strlen(jobPtr->server->name); // name is a char * of length 1025
        remoteServerName = malloc (length * sizeof(char));
        strncpy(remoteServerName, jobPtr->server->name, length);
    }
    return 0;
}

如何从中取回 remoteServerName?我尝试了以下方法:

[DllImport("example.dll")]
public static extern int example(StringBuilder remoteServerName);

var x = new StringBuilder();
example(x);
Console.WriteLine(x.ToString());

但字符串始终为空。

您需要为要返回的字符串分配一些 space。而不是:

var x = new StringBuilder();

提供容量值:

var x = new StringBuilder(1024);

您还应该删除对 malloc 的呼叫。调用者分配内存。这就是用 StringBuilder.

编组的目的

您没有正确使用 strncpy,因此未能编写空终止符。您可以像这样传递缓冲区长度:

int example(char *remoteServerName)
{
    if (doSomething(job))
        return getError(job);
    if (job->server != NULL) {
        // note that new StringBuilder(N) means a buffer of length N+1 is marshaled
        strncpy(remoteServerName, jobPtr->server->name, 1025);
    }
    return 0;
}

但这会有点浪费,因为隐含了所有的零填充。真的,strncpy 几乎没用,你应该使用不同的函数来复制,正如之前在这里多次讨论过的那样。我真的不想被卷入其中,因为它有点偏离问题。

明智的做法是将 API 设计为允许调用者也传递字符数组的长度,以便被调用者可以确保不会溢出缓冲区,这样你就不会需要像这里的代码一样使用魔法常量。