2012-09-10 129 views
3

我是C#和封送的新手。我需要在C#中使用我的C函数,但是我从C func返回的值不正确(或者我不知道如何将它转换为正确的答案)。DllImport和char Marshaling

c来源:

#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头:

extern "C" __declspec(dllexport) char *Ololo(char *arg, int &n3); 

C#源: “伯仲”

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

我已经得到了一些回报,像

对不起,我英文不好

----------------------解决--------------- --------

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

工作正常。在n3中,我得到了5和n4奥洛洛!感谢您的快速解答!

+0

btw'int&n3'不是C,它的C++表示法。 –

+0

你还没有解决任何问题,代码泄漏了字符串的内存。 –

+0

可能重复的[Char *编组在C#](http://stackoverflow.com/questions/1808581/char-marshalling-in-c-sharp) –

回答

3

public static extern IntPtr Ololo([In] char[] arg, ref Int32 n3);

IntPtr是错误的返回类型,本质上是要返回的字符串,而不是一个字符串指针。在C中,你可以使用指向你的字符串的指针,使用char*,.NET中的等价物将使用这个:[MarshalAs(UnmanagedType.LPStr)]string。这应该正确地将char*编号为string

IntPtr代表一个指针类型,它让你的实际字符串没用。

您看起来应该将StringBuilder放入您的Marshalled函数中,而不是char[]。然后至少你应该得到正确的字符串到你的C函数。

+0

我认为'IntPtr'是正确的,因为'n3'返回我1和int'IntPtr'我得到了第一个字母(o)。但为什么我有'n3' = 1?我认为它需要是5.因为我认为'[In] char [] arg'是不正确的。但是什么是正确的? – Treno1

+0

查看我编辑的答案 –

+0

@ Treno1如果你返回'IntPtr',你在.NET中的函数将永远不会给你整个字符串。 –

0

编组器不会终止char阵列。它会这样做,因为你告诉它 - 如果你告诉它。你很幸运,因为.NET中的一个char是UTF-16,这是16位宽,第二个字节将为零,因为这是UTF-16中的'o',因此给出了strlen为1。一个被管理的字符串作为一个以空字符结尾的C字符串比你似乎欣赏的要高一点点。所以,让编组完成所有工作 - 它已经知道如何完成这项工作。

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); 
} 
+0

由于[MarshalAs(UnmanagedType.LPStr)]不能​​在类,结构或接口的声明中,VS 2010认为'public static extern [MarshalAs(UnmanagedType.LPStr)] string Ololo'不正确。 – Treno1

+0

不是。您必须未能复制DLLImport属性,或将声明放在错误的位置。 – Puppy

+0

谢谢!解决了!向上! – Treno1