Alexandru
Alexandru

Reputation: 12882

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

I have the following function, written as part of another class in 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;
}

How can I get the remoteServerName back from it? I have tried the following:

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

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

But the string is always empty.

Upvotes: 1

Views: 245

Answers (1)

David Heffernan
David Heffernan

Reputation: 612854

You need to allocate some space for the string to be returned in. Instead of:

var x = new StringBuilder();

provide a capacity value:

var x = new StringBuilder(1024);

You should also remove your call to malloc. The caller allocates the memory. That is the purpose of marshalling with StringBuilder.

You are not using strncpy correctly, and so fail to write a null terminator. You could pass the buffer length like this:

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;
}

But that would be a bit wasteful, with all the zero padding that is implied. Really, strncpy is next to useless and you should use a different function to copy, as has been discussed many times before here. I don't really want to get drawn into that because it's a little off to the side of the question.

It would be prudent to design your API to allow the caller to also pass the length of the character array so that the callee can make sure not to overrun the buffer, and so that you don't need to use magic constants as the code here does.

Upvotes: 4

Related Questions