之前从来没搞过C++,最近被安排的任务需要调用C++的接口,对于一个没用过 Dependency 的小白来说,原本以为像平时的Http接口那样,协议,端口一定义,方法参数一写就没事,结果踩了无数的坑。现在从0基础开始记录。A发了一个SDK文件夹过来,先不管cpp、h、lib五花八门的后缀文件,直接看文档说明,表明需要调哪些方法。网上简单的查阅下资料,发现直接引用动态库Dll 的方式是通过 DllImport去实现,命名空间为 using System.Runtime.InteropServices;

按照文档中方法名、参数类型的说明,写下对应代码

        [DllImport("ConX.dll", EntryPoint = "add")]
public static extern int add(byte[] cfg_dir_name);
//VS2017中 方法名首字母需要大写为 Add
public void Test1()
{
int a=;
try
{
string str = "";
byte[] bts = Encoding.Default.GetBytes(str);
a = add(bts);
}
catch (Exception ex)
{ string strEx = ex.Message;
}
Console.WriteLine(a);
Console.ReadLine(); }

一运行,提示 " 试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)" ,这一般是版本不匹配的原因,确定dll 版本为64位后,将Debug中设置为 x64 即可 (32位则设置为x86),接着运行 ,会提示 " 找不到Dll的入口点 "

用 DepenDency 查看下该Dll ,发现所谓的函数名变化了,并不是add,变成了下图一长串的字符(CallingConvention.Cdecl 编码)

相关资料显示,在导出C++程序是,可以选择C方式,和C++方式,C方式不会变更函数名,C++则会,   项目右键--属性--配置属性--C/C++--高级--编译为--①C ②C++ ,当然还可以在原函数中的前面加上Extern C来限定导出后函数名不变,目前没有源码,只有dll,所以对于这种情况,只需要将变更的函数名作为入口点 赋值给 EntryPoint 即可

[DllImport("ConX.dll", EntryPoint = "?add@@YAHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z")]

接着运行,这个时候 又会提示 " 请检查PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配 " , 资料显示,调用平台的默认约定 为Winapi , 而这种变更方法后的格式 " ?方法名@@YA-----------@Z " 为Cdecl 约定,于是再次更改导入dll的代码

[DllImport("ConX.dll", EntryPoint = "?add@@YAHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z",CallingConvention=CallingConvention.Cdecl)]

如此折腾了一番,运行后, 如果报 " 无法加载 DLL“face_export.dll”: 找不到指定的程序 " 那就是路径有问题,一般处理方法如下

①直接把Dll 拷贝到 执行文件exe所在的目录下,记住通过Dependency 查看dll时,看下有没有缺失的dll ,如果没有,在将所依赖的非系统的dll 一并拷贝到 执行文件exe所在的目录下,

②使用 Dll 的绝对路径

③将 Dll 拷贝至系统的文件下,64位系统 对应的32位Dll则为SysWOW ,64为Dll 则为System32

正常情况下,到这里就没有什么大问题,如果报参数问题,那就需要查阅 C++ 对应的 C# 数据类型。匹配正确即可,关键就在于我这里仍然报错,外部组件异常,外部组件异常,外部组件异常,查阅资料显示,网上没什么好的解决方案,因为这种问题的原因五花八门,是一个很笼统的错误,可是偏偏就被我遇到了,我这边按接口中函数的申明,照葫芦画瓢写了一个C++ 的Dll,用C#调用自己写的Dll 是OK 。同事用C++调用 第三方的 Dll 也没问题(说明别人提供的Dll没问题)。这样一来就尴尬了,思路不能沉寂在这里。网上有人说是Net 版本可能不兼容,我挨个尝试一遍从3.5 切换到 4.6.1 仍是外部组件异常的错误。 最后我用VS2017 打开,调试程序,仍然是外部组件异常。现在可以排除的是 不是依赖问题(报找不到Dll),不是没加载指定Dll问题, 因为不会报入口点找不到的错误,也不是参数的问题,版本的问题已经用VS2017尝试过。还会有什么方面的原因呢?

未完待续...

最后经过翻来覆去的测试,发现问题出在 c++ 的dll上,最后重新封装了一边dll,再次调用就没问题了,看来还是自己学习的不够...

C# 调用C++的dll 那些事的更多相关文章

  1. 调用Interop.zkemkeeper.dll无法使用解决方案

    调用Interop.zkemkeeper.dll无法使用 已经注册dll成功但是还是报错 检索 COM 类工厂中 CLSID 为 {00853A19-BD51-419B--2DABE57EB61F} ...

  2. c# 传递Null的string值导致的调用C++的dll报错 Attempted to read or write protected memory.

    c# 调用C++的dll报错 Attempted to read or write protected memory:   原因是:c# 传递Null的string值导致的,将Null改为string ...

  3. Node调用C++(dll)

    最近开始搞毕设了,打算用自己拿手的js来搞,但是仿佛入坑了,Node还不是很熟.总之,兵来将挡,水来土掩嘛,带着问题学习才是最高效的. 折腾1:Node 调用 C++ 刚开始,虽然我老师把dll文件给 ...

  4. golang调用c++的dll库文件

    最近使用golang调用c++的dll库文件,简单了解了一下,特作此笔记:一.DLL 的编制与具体的编程语言及编译器无关 dll分com的dll和动态dll,Com组件dll:不管是何种语言写的都可以 ...

  5. vs2010下C++调用lib或dll文件

    注: DLL:表示链接库,包含dll,lib文件: dll: 表示my.dll文件 lib: 表示my.lib文件 C++ 调用.lib的方法: 一: 隐式的加载时链接,有三种方法 1  设置工程的 ...

  6. paip.java c# .net php python调用c++ c dll so windows api 总结

    paip.java c# .net  php python调用c++ c dll so windows api 总结 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来 ...

  7. c++builder调用VC的dll以及VC调用c++builder的dll

    解析__cdecl,__fastcall, __stdcall 的不同:在函数调用过程中,会使用堆栈,这三个表示不同的堆栈调用方式和释放方式. 比如说__cdecl,它是标准的c方法的堆栈调用方式,就 ...

  8. LabView调用C#混合模式dll

    在一些特定要求下,我们的C#可能需要制作dll给LabView进行调用,并且我们不能够保证C#的程序是完全自己写而不调用第三方的dll库.很多时候我们需要使用诸如Sqlite.Net.AForge.N ...

  9. 关于c#调用c/c++ dll遇到的问题总结

    前段时间公司做了个winform程序,需要调用c 的dll去读取卡号的程序,期间遇到些问题,下面来分享下 一.dll路径问题 相信很多开发者都会遇到这个问题,我总结了下我现在有3总方式去解决这个问题: ...

随机推荐

  1. 深入浅出MySQL++数据库开发、优化与管理维护+第2版+唐汉明 -- 存储引擎 - 数据类型 - 字符集和校验规则 -

    create schema deepInMySql;use deepInMySql; -- 查看当前默认存储引擎show variables like '%table_type%'; -- 查看当前数 ...

  2. Netty5+Jboss(Marshalling)完成对象序列化传输

    TCP在网络通讯的时候,通常在解决TCP粘包.拆包问题的时候,一般会用以下几种方式: 1. 消息定长 例如每个报文的大小固定为200个字节,如果不够,空位补空格: 2. 在消息尾部添加特殊字符进行分割 ...

  3. 解决Office 2016客户端如何同SharePoint Server2016安装在一起

    前言 Microsoft Office 2016 客户端默认使用新式验证. 在某些配置中,新式验证不受安装有 SharePoint Server 2016 的 Office 2016 客户端的支持,例 ...

  4. Nest.js 守卫

    Docs: https://docs.nestjs.com/guards 当调用者具有足够的权限时,特定路由才可用 // app.guard.ts import { CanActivate, Exec ...

  5. laravel5.4+vue+element简单搭建(gulp+laravel Elixir)(转)

    如今laravel来到5.4版本,更方便引入vue了,具体步骤如下: 下图为我动到的文件 1.下载laravel5.4 2.命令行(laravel5.4目录下):composer install 3. ...

  6. 主机配置nginx后如何获取访问者IP

    he你早的时候写了一个根据访问者ip查询天气的小接口,那时候还没得买域名,没有搞nginx,测试自然没有问题,然后随着一个小工具一块上线了,今天突然发现我的小工具有好几个人在使用了,就想写一个记录访问 ...

  7. python全栈开发 * 线程锁 Thread 模块 其他 * 180730

    一,线程Thread模块1.效率更高(相对于进程) import time from multiprocessing import Process from threading import Thre ...

  8. python全栈开发 * 30知识点汇总 * 180713

    30 re模块2一.正则表达式在线测试 在线测试工具 http://tool.chinaz.com/regex/(一).*?的用法: . 是任意字符 * 是取 0 至 无限长度 ? 是非贪婪模式.合在 ...

  9. gui小计算器的程序写法

    import java.awt.BorderLayout; import java.awt.EventQueue; import javax.swing.JFrame; import javax.sw ...

  10. One Technical Problem: Can one process load two different c libraries simutaneously, such as uclibc and glibc?

    For some special reasons, there is a possible case which need to load uclibc and glibc in one proces ...