Reputation: 139
I'm newbie at C# and Marshaling. I need to use my C func in C#, but i have an incorrect return value from C func (or I don't know how to convert it to correct answer).
C source:
#include "main.h"
char *Ololo(char *arg, int &n3)
{
char *szRet;
szRet=(char*)malloc(strlen(arg)+1);
strcpy(szRet,arg);
n3 = strlen(szRet);
return szRet;
}
C header:
extern "C" __declspec(dllexport) char *Ololo(char *arg, int &n3);
C# source:
class Program
{
[DllImport(@"F:\Projects\service\dll\testDLL2.DLL", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
public static extern IntPtr Ololo([In] char[] arg, ref Int32 n3);
static void Main(string[] args)
{
string n1 = "ololo";
char[] chars = new char[n1.Length];
chars = n1.ToCharArray();
Int32 n3 = 0;
IntPtr result;
result = Ololo(chars, ref n3);
string n4 = Marshal.PtrToStringUni(result,n3);
Console.WriteLine(n4);
}
}
I've got return something like "o?? ?"
Sorry for bad English
----------------------Solved-----------------------
class Program
{
[DllImport(@"F:\Projects\service\dll\testDLL2.DLL", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
public static extern IntPtr Ololo([MarshalAs(UnmanagedType.LPStr)]string arg, ref Int32 n3);
static void Main(string[] args)
{
string n1 = "ololo";
Int32 n3 = 0;
int n2 = n1.Length;
IntPtr result;
result = Ololo(n1, ref n3);
string n4 = Marshal.PtrToStringAnsi(result, n3);
Console.WriteLine(n4);
}
}
That works fine. In n3 i ve got 5 and in n4 ololo! Thank s for quick answers!
Upvotes: 4
Views: 14256
Reputation: 146910
The marshaller does not NULL terminate char
arrays for funsies. It will do it because you told it to- if you told it to. You are fortunate because a char
in .NET is UTF-16, and this is 16 bits wide- and the second byte will be zero because that is 'o'
in UTF-16, thus giving a strlen of 1. The actual effort to pass in a managed string as a null-terminated C string is a tad higher than you seem to appreciate. So let the marshaller do all the work- it already knows how to do this job.
public static extern [MarshalAs(UnmanagedType.LPStr)]string Ololo(
[MarshalAs(UnmanagedType.LPStr)]string arg,
ref int n3
);
static void Main(string[] args)
{
string n1 = "ololo";
Int32 n3 = 0;
string n4 = Ololo(chars, ref n3);
Console.WriteLine(n4);
}
Upvotes: 0
Reputation: 63190
public static extern IntPtr Ololo([In] char[] arg, ref Int32 n3);
IntPtr
is the wrong return type, as essentially you want to return the string, not a pointer to the string. In C you can use a pointer to your string by using char*
, the equivalent in .NET would be to use use this: [MarshalAs(UnmanagedType.LPStr)]string
. This should marshall the char*
to a string
correctly.
IntPtr
represents a pointer type, which to get your actual string is useless.
Also looks like you should be taking a StringBuilder
into your Marshalled function, and not a char[]
. Then at least you should be getting the correct string to your C function.
Upvotes: 4