C# : 调用C++动态库(dll)

在实际软件开发过程中,由于公司使用了多种语言开发,在C#中可能需要实现某个功能,而该功能可能用其他语言已经实现了,那么我们可以调用其他语言写好的模块吗?还有就是,由于C#开发好的项目,我们可以利用reflector等反编译工具反编译出其源代码,所以对于一些核心算法,我们不希望被别人知道,因此为了增强代码的安全性,我们需要将一些核心算法用C或C++来编写,然后用C#来调用这些已经写好的接口。在面对以上情况时,我们该怎么做呢?


 方案一:重新实现
        针对第一种情况,我们可以将C或者C++功能用C#来重新实现,这样的话代码比较统一,维护比较方便,但是这样的话增加了软件开发的成本,把C++的代码功能改成C#涉及到指针和内存的操作比较繁琐,况且有开发好的模块为什么不重复利用呢?针对第二种情况就不能得到有效解决,虽然可以使用混淆器对代码进行混淆,但是任然不是很安全。

 方案二:封装COM组件
        我们可以将C或者C++的函数封装成COM组件,在C#中调用时比较方便,但是COM组件需要注册,而且多次注册可能也会导致一些问题,同时在处理C或者C++的类型与COM组件的类型转换的时候也可能有些麻烦。


 方案三:使用动态链接库
        我们可以直接调用C或者C++已经写好的动态链接库,这样比较方便,这样很好的解决了上述问题。

 

        在实际项目中,我们需要使用C#调用C++的一些接口,因此我使用的是方案三采用动态库,下面我就在实际中怎么处理的进行说明。
        在调用动态库的过程中我也遇到了以下一些问题:
        1、C++中有指针,C#中需要使用指针吗?
        由于C++中的动态库中有指针参数,因此我也是用.NET的不安全代码,使用了C#的指针,但是最后也还是出现了一些问题,如在C#中传入的参数是一个二维数组时就出现了问题,这个问题我在网上找了好多资料也没有解决,最后和c++程序员商量了下改变了传入参数的参数类型。最后也没有使用指针。
        2、C#和C++中的类型如何转换呢?
        虽然C#和C++比较类似,但是其给我们的参数类型我们要与C#的参数类型一一对应起来,因此我找了一些资料把其类型一一对应了,具体看后续说明。
        3、C++写好的动态库放到那个位置呢?
        关于C++动态库的位置也是个问题,在应用中我们使用了相对路径和绝对路径进行测试,有的发现在VS中可以调用到,但是发布后发现无法调用到动态库,最后只要把动态的dll放到系统的目录system32下面才解决了改问题,目前还没找到其他的方法,如有其他的更好方法还请大家指点。
        4、如何反编译C++的dll的名称,端口?
        可以通过Dependency Walker工具进行反编译查看别人写的动态库的信息
        5、还有其他的一些细节,如C#调用动态库需要指定其编码、代码写法等等

c#调用c++动态库一般我们这样写

[DllImport("UCamer.dll", CallingConvention = CallingConvention.Winapi)]
public extern static void Disp_Destroy(IntPtr hShow);
DllImport的第一个参数UCamer.dll是动态库dll的路径,此dll放在程序运行的根目录或者c:windows/sytem32下

  CallingConvention 参数是c#调用c++的方式 是个枚举 msdn解释如下

  

Cdecl调用方清理堆栈。这使您能够调用具有 varargs 的函数(如 Printf),使之可用于接受可变数目的参数的方法。 
FastCall不支持此调用约定。
StdCall被调用方清理堆栈。这是使用平台 invoke 调用非托管函数的默认约定。 
ThisCall第一个参数是 this 指针,它存储在寄存器 ECX 中。其他参数被推送到堆栈上。此调用约定用于对从非托管 DLL 导出的类调用方法。 
Winapi此成员实际上不是调用约定,而是使用了默认平台调用约定。例如,在 Windows 上默认为 StdCall,在 Windows CE.NET 上默认为 Cdecl。 

 从上面来看Winapi方式是根据系统自动选择调用规约的。 而thisCall是对c++类的调用方法。 所以 一般情况下我们选择Winapi就可以了。

例子:

#region 无标题窗体右键任务栏弹出菜单代码[DllImport("user32.dll", EntryPoint = "GetWindowLong", CharSet = CharSet.Auto)]public static extern int GetWindowLong(HandleRef hWnd, int nIndex);[DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]public static extern IntPtr SetWindowLong(HandleRef hWnd, int nIndex, int dwNewLong);protected override CreateParams CreateParams{get{const int WS_MINIMIZEBOX = 0x00020000;  // Winuser.h中定义   CreateParams cp = base.CreateParams;cp.Style = cp.Style | WS_MINIMIZEBOX;   // 允许最小化操作   return cp;}}#endregion#region 窗体拖动代码[DllImport("user32.dll")]public static extern bool ReleaseCapture();[DllImport("user32.dll")]public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);public const int WM_SYSCOMMAND = 0x0112;public const int SC_MOVE = 0xF010;public const int HTCAPTION = 0x0002;private void Login_MouseDown(object sender, MouseEventArgs e){ReleaseCapture();SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);}#endregion[DllImport("wininet.dll")]private extern static bool InternetGetConnectedState(out int conn, int val);private void btnNetTest_Click(object sender, EventArgs e){int Out;if (InternetGetConnectedState(out Out, 0) == true){MessageDxUtil.ShowTips("Internet网络连通!");}else{MessageDxUtil.ShowTips("Internet网络不通!");}}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/252101.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python3.5以上版本lxml导入etree报错Unresolved reference

Web抓取Web站点使用HTML描述,这意味着每个web页面是一个结构化的文档。有时从中 获取数据同时保持它的结构是有用的。web站点不总是以容易处理的格式, 如 csv 或者 json 提供它们的数据。 这正是web抓取出场的时机。Web抓取是使用计算机程序将web页面数据…

linux设置history历史记录

#说明export HISTSIZE1000 #设置历史记录显示1000行export HISTTIMEFORMAT%F %T #设置历史记录格式 999 2017-08-15 10:58:32 #修改vim /etc/profilesed -i "s/\(HISTSIZE\).*/\11000/" /etc/profilesed -i "/HISTSIZE/aexport HISTTIMEFORMAT%F %T " /et…

STL-容器库101--array【C11】

1. 原型 C11提供 template < class T, size_t N > class array;T&#xff1a; 元素类型&#xff0c;以 array::value_type 作为别名使用&#xff1b;N&#xff1a; array中元素大小&#xff1b; 固定size的序列容器&#xff1b;初始化时&#xff0c; array对象不保存任何…

C#:向C++封送结构体数组

在使用第三方的非托管API时&#xff0c;我们经常会遇到参数为指针或指针的指针这种情况&#xff0c; 一般我们会用IntPtr指向我们需要传递的参数地址&#xff1b; 但是当遇到这种一个导出函数时,我们如何正确的使用IntPtr呢&#xff0c; extern "C" __declspec(dll…

其它综合-CentOS7 忘记root密码

CentOS7 忘记root密码 长时间不用的 CentOS 机器再次开机的时候忽然忘记了密码&#xff0c;总不能就重装一台吧&#xff0c;还有好多服务在机器上&#xff0c;于是决定重置root的密码。   如果是已经开启的机器&#xff0c;需要进行关闭&#xff0c;重新启动。在启动选择内核…

left join on and 与 left join on where的区别

数据库在通过连接两张或多张表来返回记录时&#xff0c;都会生成一张中间的临时表&#xff0c;然后再将这张临时表返回给用户。 在使用left jion时&#xff0c;on和where条件的区别如下&#xff1a; 1、 on条件是在生成临时表时使用的条件&#xff0c;它不管on中的条件是否为真…

spring boot高性能实现二维码扫码登录(中)——Redis版

前言 本打算用CountDownLatch来实现&#xff0c;但有个问题我没有考虑&#xff0c;就是当用户APP没有扫二维码的时候&#xff0c;线程会阻塞5分钟&#xff0c;这反而造成性能的下降。好吧&#xff0c;现在回归传统方式&#xff1a;前端ajax每隔1秒或2秒发一次请求&#xff0c;去…

C# :socket 通讯基础使用实例

们在讲解Socket编程前&#xff0c;先看几个和Socket编程紧密相关的概念&#xff1a; TCP/IP层次模型当然这里我们只讨论重要的四层 01&#xff0c;应用层(Application)&#xff1a;应用层是个很广泛的概念&#xff0c;有一些基本相同的系统级TCP/IP应用以及应用协议&#xff0…

IBM发表论文:可能已找到处理量子计算退相干的方法

在《自然》杂志最近发表的一篇论文中&#xff0c;IBM和其他机构的研究人员设计了两种量子算法&#xff0c;利用变分量子电路和量子核估计器来训练一种支持向量机分类器。这两种算法背后的关键思想是使用量子状态空间作为特征空间表示&#xff0c;有效地构建映射&#xff0c;从原…

PHP + NGINX 控制视频文件播放,并防止文件下载

最简单的方法是使用NGINX的 internal 功能 server { listen 80; server_name www.xxx.com;  location / { index index.php index.html index.htm; root /xxx; if (!-e $request_filename) { rewrite ^/index.php(.*)$ /index.php?s$…

可视化调试工具

rosrun rqt_console rqt_console # 查看日志消息&#xff0c;可filter、highlight指定级别。 rosrun rqt_logger_level rqt_logger_level # 可设在日志记录器的严重级别 rosrun rqt_topic rqt_topic # 显示topic调试信息 rosrun rqt_publisher rqt_publisher # 在界面中管理ro…

C#:委托基础与事件

通过以下思维导图&#xff0c;学习委托的基本概念&#xff0c;后面着重讲解委托的运用&#xff0c;希望通过最简单的方式收获更多的知识。 1.委托的各种写法 1、委托 委托名new 委托&#xff08;会调用的方法名); 委托名&#xff08;参数&#xff09;; 2、委托 委托名 会调用…

Git Bash关键命令

1.默认目录是C:\Users\用户名 2.切换目录&#xff1a;$cd c:\\windows 3.切换到上级目录&#xff1a;cd ..&#xff0c;中间有空格 4.列出某目录所有文件&#xff0c;相当于DOS下的dir&#xff1a;ls c:\\windows 5.查看配置信息&#xff1a;git config --list 以下是显示信息 …

C#:invoke 与 BeginInvoke使用区别

invoke和begininvoke 区别 一直对invoke和begininvoke的使用和概念比较混乱&#xff0c;这两天看了些资料&#xff0c;对这两个的用法和原理有了些新的认识和理解。 首先说下&#xff0c;invoke和begininvoke的使用有两种情况&#xff1a; 1. control中的invoke、begininvoke。…

Django基本命令

Django基本命令 1.创建一个Django 项目 django_admin.py startproject mysite当前目录下会生成mysite的工程&#xff0c;目录结构如下&#xff1a; manage.py ----- Django项目里面的工具&#xff0c;通过它可以调用django shell和数据库等。settings.py ---- 包含了项目的默认…

Git忽略规则.gitignore梳理

对于经常使用Git的朋友来说&#xff0c;.gitignore配置一定不会陌生。废话不说多了&#xff0c;接下来就来说说这个.gitignore的使用。首先要强调一点&#xff0c;这个文件的完整文件名就是".gitignore"&#xff0c;注意最前面有个“.”。 一般来说每个Git项目中都需…

第二周CoreIDRAW课总结

1.这节课学到了什么知识&#xff1f; 学到了图像的复制&#xff0c;再制鼠标复制&#xff0c;重复&#xff0c;还有对象的对齐&#xff0c;对象的分布顺序。 2.有哪些心得体会&#xff1f; 做了课本的练习&#xff0c;会用窗口里面的泊坞窗造型命令也作出了一个作品。 3.这节课…

axios关于针对请求时长策略设计的思考

前言 在我们的业务请求中&#xff0c;有很多时候会针对有不同时长的需求策略性设置。这里针对这个需求进行详细的展开。 针对这种情况&#xff0c;我们的timout的一般是根据请求地址来的&#xff0c;所以核心处理技巧便是如何根据不同的request地址去设置不同的timeout. 我们之…

C#:WinForm无边框窗体移动方法、模仿鼠标单击标题栏移动窗体位置

方法一&#xff1a;直接通过修改窗体位置从而达到移动窗体的效果 方法二&#xff1a;直接伪装发送单击任务栏消息&#xff0c;让应用程序误以为单击任务栏从而移动窗体 方法一 1.定义一个位置信息Point用于存储鼠标位置 private Point mPoint; 2.给窗体等控件增加MouseDown…

Python 字典删除元素clear、pop、popitem

同其它python内建数据类型一样&#xff0c;字典dict也是有一些实用的操作方法。这里我们要说的是字典删除方法&#xff1a;clear()、pop()和popitem()&#xff0c;这三种方法的作用不同&#xff0c;操作方法及返回值都不相同。接下来就来查看下这些字典特定方法的具体用法是什么…