【问题标题】:How to use C++ dll from C#如何在 C# 中使用 C++ dll
【发布时间】:2015-05-20 04:08:11
【问题描述】:

我正在尝试在我的 c# 项目中包含 c++ 库 (DLL),但每次我这样做时,我都会在 VS2012 中收到以下错误消息

A reference to 'C:\Users\HiepDang\Desktop\mydll.dll' could not be added. Please make sure that the file is accessible, and that it is a valid assembly or COM component.

当我尝试添加 Com+ 组件时,我在窗口中收到以下错误消息

一个或多个文件不包含组件或类型库。无法安装这些文件。

发生错误 80110425。

发生未知错误。您应该检查所有文档以获取解决方案。如果没有更多信息,请联系技术支持

我正在关注线程 herehere,但我的问题没有解决。

在 C++ 中,我可以像这样使用 dll:

    //Header
    extern "C" __declspec( dllimport ) int mymethod(const char *key, char *data, size_t buflen);
    
    //Code test
    const char* key = "test";

    char* data = new char[1024];
    int buflen = 1024;
    int result = mymethod(key,data, buflen);

在 C# 中,我使用 dll 作为:

    //define dll
    [DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern int mymethod([MarshalAs(UnmanagedType.LPTStr)]string key, [MarshalAs(UnmanagedType.LPTStr)]string data, uint buflen);

    //method test
    private static int testdll() 
    {
        string key = "123456789";
        string buf = string.Empty;
        mymethod(key, buf, 1024);
        return 0;
    }

你能告诉我任何解决方案吗?

P.s: 我的英文不好。如有不便,敬请见谅

已编辑:我解释了 dll 中方法中的变量。 “key”作为字符串输入有8-13个字符,mymethod会被加密生成“buf”。我需要“buf”变量。

【问题讨论】:

  • 如链接所说,使用DllImport不要尝试通过右键单击引用并选择添加来添加引用。只需使用您现有的DllImport c# 代码
  • @MickyDuncan:感谢您的回复。但是我发布的 C# 代码不符合我的要求。当 mymethod 调用时,“buf”的值必须改变。按照 C# 代码,我只是收到一条错误消息,“'key' 的值无效”。当 key 的变量没有足够的 8 个字符时会发生这种情况。
  • 更新您的问题以反映这些新要求
  • 请在运行代码时填写完整的错误异常消息。它将帮助我们区分您的问题到底是什么。
  • @M.Mahdipour:C# 代码出现无异常错误。使用 C++ 代码,当我使用 key =“123456789”调用方法时,我得到 buf =“2995796360”。如果 key 不在 8-13 个字符之间,您必须收到消息:“'key' 的值无效”。所有返回的消息都是由其他人定义的。使用 C# 代码,当我使用 key = "123456789" 调用方法时,我会收到消息,例如 key has not 在 8-13 个字符之间。

标签: c# c++ .net dll


【解决方案1】:

在 C# 中,您必须使用 StringBuilder()

//define dll
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int mymethod(string key, StringBuilder data, IntPtr buflen);

//method test
private static int testdll() 
{
    string key = "123456789";
    StringBuilder buf = new StringBuilder(1024);
    mymethod(key, buf, (IntPtr)buf.Capacity);
    string buf2 = buf.ToString()
    return 0;
}

请注意,size_t 的大小是 IntPtr,因为它在 x86 上是 4 个字节,在 x64 上是 8 个字节。

【讨论】:

  • 感谢您的解决方案。我必须遵循,但仍然发生错误。
  • @HiepDang 您必须将.dll 放在.exe 的同一文件夹中,并且您必须知道您的.dll 是编译为32 位还是64 位。然后将 C# 项目设置为 Properties->Build->Platform Target x86,如果 dll 是 32 位,如果 dll 是 64 位,则设置 x64。
  • mydll 是 32 位的,然后我也设置了 Platform Target x86。我想我必须使用 C++/CLI 来解决这个错误。感谢您的帮助!
  • 我已经解决了我的问题。我已经编辑了您的代码以改进答案。谢谢!
【解决方案2】:

在您的 cpp 项目中, 改变

extern "C" __declspec( dllimport )

extern "C" __declspec( dllexport )

并将生成的 cpp dll 文件“mydll.dll”复制到 C# 项目的 outdir 中。

顺便说一句,如果第二个参数数据不是字符串而是原始二进制数据,最好使用 byte[] 而不是 char*。

[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int mymethod([MarshalAs(UnmanagedType.LPTStr)]string key, byte[] data, uint buflen);

字节数组被自动编组。

Reference on MSDN

像下面这样使用它。

var key = "A key";
var data = new byte[10];
//fill data
mymethod(key, data, (uint)data.Length);

【讨论】:

  • 不像你想的那样。你看到在 Visual C++ 中使用的 Cpp 代码 sn-p,它可以很好地工作。但是我想在C#中使用mydll.dll,不知道怎么办?
【解决方案3】:

另外,因为我的 DLL 是非托管的(意味着它是一种非托管语言,如 C 或 C++),所以根据 DllImport 的规范,“表明属性方法被非托管 DLL 作为静态入口点公开”。为什么我不能使用这个“DllImport”? 如果它是一个 c++ com 对象,如果你用 regsvr32 注册它,你可以在 Visual Studio com 引用选项卡中添加对 dll 的引用,通常 Visual Studio 会创建一个 dll(我认为它称为运行时可调用包装器),你可以看到它是用名称 oflibrary.interop.dll。因此,如果是 com 对象,MyExecRefsDll.dll 将变为 MyExexRefs.Interop.dll。但是,当您添加参考 Visual Studio 时,通常会在托管代码中自动为您执行此操作。如果您通过在 c++ 中使用 atl 模板将 c++ dll 创建为 com 对象,则更容易从 dotnet 访问(我从引用另一个 dll 文件的 dll 引用非托管 c++ 代码(没有从第二个 dll 复制的代码我只是引用 tlb 、lib、dll 文件,Visual Studio 完成其他所有工作。

【讨论】:

    猜你喜欢
    • 2021-12-22
    • 2013-04-26
    • 2020-10-14
    • 1970-01-01
    • 2018-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多