从 c# dll 调用/编组字符串到非托管代码

Posted

技术标签:

【中文标题】从 c# dll 调用/编组字符串到非托管代码【英文标题】:Calling/Marshalling strings from c# dll to unmanaged code 【发布时间】:2012-12-29 16:37:24 【问题描述】:

我正在尝试从非托管的第 3 方应用程序调用 dll 中的 c# 函数 - metatrader

我已听从 Calling C# dll from unmanaged code 的建议,但是关于编组字符串的示例不起作用。

注意:我已经成功地从参考中调用了整数加法示例(函数“Add”),它端到端地工作没有问题,所以我知道问题与字符串有关。即,“ReplaceString”功能不起作用。我也看过RobertGisiecke网站,但是那里没有字符串示例,或者我太笨了。

我在 metatrader 中得到的错误信息是:

15:27:40 2009.11.10 00:01 MT4LibTest EURUSD,H1:函数 'ReplaceString' 调用来自 dll 'Testme.dll' 严重错误 c0000005 在 040B031B。

平台是 Windows Server 2012 (64bit) 我已经编译到 x86 因为 Metatrader 是一个 x86 程序

还有一件事:我对VS世界不是很有经验,所以我希望有人能提供帮助

谢谢

C#代码:

[DllExport("ReplaceString", CallingConvention = CallingConvention.StdCall)]
    public static int ReplaceString(
        [In, Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder str,
        [MarshalAs(UnmanagedType.LPWStr)]string a, 
        [MarshalAs(UnmanagedType.LPWStr)]string b)
    
        str.Replace(a, b);

        if (str.ToString().Contains(a)) return 1;
        else 
            return 0;
    

调用函数(Metatrader):

#import "MT4Lib.dll"
    int ReplaceString(string & str,string a,string b);
    int Add(int x, int y);
#import
    string str="A quick brown fox jumps over the lazy dog";
    string stra = "fox";
    string strb = "cat";        

    Print(str);
    Print(ReplaceString(str,stra,strb));
    Print(str);

编辑: 我应该明确指出,允许编写“脚本”的 metatrader API 不允许完整的 C++ 类型。所以没有 char,没有 wchar,当然也没有指向这些类型的指针。只有“字符串”。

【问题讨论】:

欢迎来到 ***。您不能将 C++ 字符串传递给 C# 应用程序。您可能需要将其设为wchar *。另请参阅相关问题(右侧)。例如:***.com/questions/643202/… 您不能 pinvoke 将 C++ 对象作为参数的函数。 为了做这个'C++调用C#'的事情,我建议你改用COM。在 C# 中创建一个 COM 对象并在 C++ 中使用它。 【参考方案1】:

找到解决方案!

首先,感谢所有回复的人。掌握新技术(对我来说)有点挑战)。 @Jim:请参阅我添加的编辑。 MQL(metatrader 语言)可能基于 C++,但已受到应用程序设计者的严重束缚。所以没有 wchar 类型。 @Simon:添加对 NuGet 包“UnmanagedExports”的引用将为您放置包装器并处理 CIL 修复,因此您可以专注于您的代码。我在问题中包含的链接对此进行了详细说明。

代码存在两个问题:

    在给出的示例代码中,c# 函数中的字符串参数被声明为 LPWStr(宽字符串)。在调试器中查看它们显示它们中有中文字符。 LPStr 工作正常。

    public static int ReplaceString(
        [In, Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder str,
        [MarshalAs(UnmanagedType.LPStr)]string a, 
        [MarshalAs(UnmanagedType.LPStr)]string b)
    

    示例代码还有一个指向字符串的指针,该指针在调用者(本机)代码中声明为参数。删除它,并使用 StringBuilder 类来更改托管 c# 代码中的字符串,工作正常。

    #import "MT4Lib.dll"
        int ReplaceString(string str,string a,string b);
        int Add(int x, int y);
    #import
    

【讨论】:

如果有人试图将字符串编组到 MQL 终端,此链接将非常有帮助:mql5.com/en/articles/249

以上是关于从 c# dll 调用/编组字符串到非托管代码的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 和非托管 C++ 之间传递自定义对象

将指针从非托管代码返回到托管代码

C++ <--> C# 修改编组的字节数组

将多维数组从托管代码传递到非托管代码

从非托管 c++ 调用 C# 函数(通过托管包装器)

从 C# 调用非托管 DLL,将结构作为参数传递