从C#传回参数到C ++ Dll的正确方法是什么?

时间:2014-11-21 23:00:29

标签: c# c++ visual-studio pinvoke

我正在研究一个C ++ DLL,它应该能够接收并将一些参数传递回C#应用程序。

我能够做到这一点,这很好。至少我是这么认为的。代码在我的电脑上工作正常,但不在我同事的电脑上。在他的电脑上,相同的代码(在我的电脑上没有错误地工作)产生不同的输出或产生错误。所以基本上它表现得非常奇怪。

C ++函数:

extern "C"
{
   __declspec( dllexport ) BOOL __stdcall MyFunction( char * StringIn, char *StringOut, BOOL bState );
}

我在C#中以这种方式使用它:

    [DllImport( @"PathToMyDll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall )]
    public static extern bool MyFunction( string StringToDLL, StringBuilder StringFromDLL, bool bState );

    static void Main(string[] args)
    {
        int bufferSize = 16384;

        string StringToDLL = "This is a sample string";
        StringBuilder StringFromDLL = new StringBuilder( bufferSize );

        Console.WriteLine( "Return value      = " + MyFunction( StringToDLL, StringFromDLL, true ).ToString() );
        Console.WriteLine( "Sent to DLL       = " + StringToDLL.ToString() );
        Console.WriteLine( "Returned from DLL = " + StringFromDLL.ToString() );

        Console.ReadLine();
    }

所以我的问题是:
难道我做错了什么?或者Visual Studio中是否存在可能导致此类行为的某些设置?另外,我应该如何在C#中为StringOut正确分配内存?有一种情况可能会使StringOut比buffersize更大,但我不知道它究竟有多大?(我只知道它在DLL中) 有没有人有任何想法为什么相同的代码在不同的PC上表现不同?

提前致谢!

2 个答案:

答案 0 :(得分:1)

根据问题中的信息,您的代码是正确的。问题可能在于其他地方。显而易见的地方是非托管代码。我建议你调试一下。

您的代码是等待发生的缓冲区溢出。如果不知道它的大小,被调用者如何避免超越缓冲区?选项包括:

  1. 将缓冲区长度传递给非托管代码。
  2. 使用BSTR,通过分配共享COM堆来允许任意长的字符串。

答案 1 :(得分:0)

如果这有帮助,这就是我将基于C ++的DLL与C#接口的方式。

[DllImport("MyDLL.DLL", CharSet=CharSet.Ansi,ExactSpelling=true, 
           CallingConvention=CallingConvention.StdCall)]
public static extern int MyFunction 
(MarshalAs(UnmanagedType.LPTStr)]StringBuilder strinIn, 
[MarshalAs(UnmanagedType.LPStr)]StringBuilder stringOut);

所以区别在于我指定了编组类型。

C ++ DLL(导出为' C'函数)将具有以下原型:

LONG WINAPI MyFunction(const char *In, char *Out);

注意:我不是 C#专家。这就是我需要做的才能让我的C ++ DLL函数被C#应用程序调用。