【问题标题】:native C++ dll/C# Problem of memorynative C++ dll/C# 内存问题
【发布时间】:2011-06-27 09:05:59
【问题描述】:

我有这个错误

附加信息:试图读取或写入受保护的内存。这通常表明其他内存已损坏。

你知道为什么吗?我真的卡住了……

我的代码:

原生 c++

    extern "C" void __declspec(dllexport) Mafonc(string nom);

void __declspec(dllexport) Mafonc(string nom)
{
    string tom = nom;
}

c#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

using System.Runtime.InteropServices;
using System.Security;

namespace TradeInterface
{
    static class Program
    {
        [DllImport("TradeEngine.dll", CharSet = CharSet.Ansi,
            CallingConvention = CallingConvention.StdCall,
            ExactSpelling = true),
        SuppressUnmanagedCodeSecurity]
        public static extern void Mafonc(string nom);

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            Mafonc("E:\\DossierProjet");

            Application.Run(new Form1());
        }
    }
}

【问题讨论】:

  • 非托管DLL中字符串的定义是什么?如果它是一个字符指针,正如我猜测的那样,那么你不能只是复制指针并在以后使用它,而是需要复制字符串本身(strcpy 或类似)。
  • 我不明白你在说什么。在我的 C++ 代码中,字符串是来自 String.h 的真实字符串。

标签: c# c++ dll memory-leaks unmanaged


【解决方案1】:

在我的 C++ 代码中,字符串是来自 String.h 的真实字符串。

&lt;string.h&gt; 标头中没有名为“string”的类型,只有来自&lt;string&gt; 的 std::string。 pinvoke marshaller 无法创建 C++ 对象。您必须使用 C 字符串:

extern "C" __declspec(dllexport)
void Mafonc(const char* nom)
{
    std::string tom(nom);
}

在 C# 中需要此声明:

    [DllImport("TradeEngine.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern void Mafonc(string nom);

请注意,字符串转换是有损的。您可以使用 const wchar_t* 和 std::wstring 来避免这种情况。

【讨论】:

  • 请注意,在编组字符串时,最好使用 MarshalAs 属性明确声明您想要的非托管类型。
  • 谢谢,现在可以了。我对一个小字符串有很多问题我将如何构建我的应用程序?嗯。 :( 你认为在本机代码和 C# 之间构建代理 C++/CLI dll 对我来说更快更安全吗?我们可以说我是菜鸟。
  • 通过 C++/CLI DLL 的通信不一定会更快,因为仍然需要对数据进行编组。一般来说,编组有点慢 => 如果可能的话,你应该使用“笨拙”而不是“健谈”的接口,即很少有大量数据的调用,而不是很多数据很少的调用。
  • 我正在用 C# 中的 winform 做一个应用程序,核心必须是 C++ 所以对你来说最好是用 Win32 用 C++ 构建应用程序或继续使用 WinForm。(Win32 吓到我了)(对不起,如果不是真的关于第一个问题)
【解决方案2】:

extern "C" void __declspec(dllexport) Mafonc(string nom);

诚然,我并不是 100% 了解 extern "C" 的工作原理,但我很确定您不允许使用 C++ 类型调用它。我假设这是一个std::string,但你没有把命名空间限定在它上面。

非常确定,即使您可以在那里使用 std::string,C# 也不会传递 std::strings。在 .NET 中,字符串是一种不同的对象。因此,您需要一些特殊的编组代码来转换为 C++ 可以理解的类型。

或者你标记为“C++”的东西真的是一个 C++/CLI 应用程序吗?因为那是不同的东西。

【讨论】:

  • 我的 C++ dll 是一个非托管/本机 C++ Dll。即使没有 extern 'C' 我也有同样的问题。我需要做什么?
  • @Nazka:您需要学习如何将字符串从托管可执行文件发送到本机 DLL。我向您保证,它不会涉及使用 C++ 类的本机 DLL;很有可能需要char*TCHAR*
【解决方案3】:

由于 ypu 在 C++ 中填充字符串,因此您应该将 StringBuilder 作为参数传递。即试试这个:

[DllImport("TradeEngine.dll", CharSet = CharSet.Ansi,
            CallingConvention = CallingConvention.StdCall,
            ExactSpelling = true),
        SuppressUnmanagedCodeSecurity]
        public static extern void Mafonc(StringBuilder nom);

那么你确定调用约定是正确的吗?不是 CallingConvention.Cdecl 吗?

【讨论】:

  • 以及我是如何编写 Mafonc("E:\\DossierProjet");最后,因为我有 2 条错误消息“匹配'TradeIn...' 的最佳重载方法有一些无效参数”和“无法从 'string' 转换为 'System.Text.StringBuilder'。
  • @Nazka 您必须更改 c# 代码,在调用函数之前创建 StringBuilder 的实例,然后传递给函数。然后使用 ToString 方法返回所需的字符串。
【解决方案4】:

您不能编组 C++ std::string。有关可以编组的类型,请参阅 marshalling stringsUnmanagedType。因此,您需要将其编组为 UnmanagedType.LPStr 或 UnmanagedType.LPWStr,并更改您的非托管 DLL。此外,调用约定很可能是 Cdecl。把这些放在一起:

void __declspec(dllexport) Mafonc(LPSTR nom)
{
    // Do something with nom
}

[DllImport(
    "TradeEngine.dll",
    CharSet = CharSet.Ansi,
    CallingConvention = CallingConvention.Cdecl,
    ExactSpelling = true),
    SuppressUnmanagedCodeSecurity]
public static extern void Mafonc([MarshalAs(UnmanagedType.LPStr)]string nom);

【讨论】:

  • Ups 我有这个:“无法在 DLL 'TradeEngine.dll' 中找到名为 'Mafonc' 的入口点。”
  • 您当然还需要 extern "C" 部分以及使用该方法的 C# 代码。我只是写了需要更改的部分。
【解决方案5】:

尝试关注,

  [DllImport("TradeEngine.dll",CallingConvention = CallingConvention.Cdecl)]
            private static  extern void Mafonc(StringBuilder data);

你的本地方法在哪里,

extern "C" _declspec(dllexport) void Mafonc(std::string data)
{
    string xyz=data;

}

IJW

【讨论】:

    猜你喜欢
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多