I'm trying to interact with a DLL library created in Delphi. In C++, I made this call perfectly fine:
for(int y = 1; y <= 12; y++)
{
char * chanName = (char *) malloc(21);
memset(chanName,0,21);
channelName(y,20,chanName);
...
}
Where channelName
is type defined as typedef int (CALLBACK* ChannelName)(int,int,char*);
Now I'm trying to do the same thing in C#. I've searched and found that StringBuilder
is commonly used as a char pointer for DLL functions. Here is how I declared my function:
[DllImport("myDLL.dll")]
public static extern int ChannelName(int x, int y, StringBuilder z);
And here is how I'm trying to call it:
for (int x = 0; x < 12; x++)
{
StringBuilder b = new StringBuilder(100);
DLLInterface.ChannelName(x+1, b.Length, b);
Console.WriteLine(b.ToString());
}
This is just making the console print out jibberish, for example:
☺ §
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
☺ î☺8f9
I remember running into a similar problem in C++ which is why I memset
the memory that I malloc
to 0. I tried to find an equivalent in C#, but maybe it's an issue with the StringBuilder
instead? In case my question isn't very clear, I just want to be able to pass a string into my function, have the function fill it up, and then print it out. Strings are immutable in C# and no good pointer options exist which is why I'm trying StringBuilder
.
In .NET, strings (and StringBuilders) are 16-bit Unicode characters. My guess is that you native function deals in 8-bit ASCII characters. You need to tell the Marshaller how to convert the characters when marshalling them. Change your DllImport attribute like so:
Updated
Also you should specify the [Out] attribute on the StringBuilder so that the Marshaller only marshals on the way out as you are passing nothing on the way in.
Updated Again
The [In,Out] attribute is redundant (that's the default), however putting it there makes it explicit that you know you desire both In and Out copying.
Updated Again
It looks like the (poorly named) 'y' parameter is the length of the char * buffer passed in and my guess is that it returns the number of characters written into the buffer. If that is the case, I would wrap this invocation in a more natural C# way: