将halcon导出的c++程序打包成dll库
1、从“文件”菜单中,选择“新建”,然后选择“项目…”。
2、从“项目类型”窗格中选择“Visual C++”下的“Win32”。
3、从“模板”窗格中,选择“Win32 控制台应用程序”。
4、为项目选择一个名称,如“MathFuncsDll”,并将其输入“名称”字段。为解决方案选择一个名称,如“DynamicLibrary”,并将其输入“解决方案名称”字段。
5、按“确定”启动 Win32 应用程序向导。在“Win32 应用程序向导”对话框的“概述”页中,按“下一步”。
6、从“Win32 应用程序向导”中的“应用程序设置”页中,选择“应用程序类型”下的“DLL”(如果可用),或者选择“控制台应用程序”(如果“DLL”不可用)。某些版本的 Visual Studio 不支持使用向导创建 DLL 项目。您可以稍后对此进行更改,以将项目编译为 DLL。
7、从“Win32 应用程序向导”的“应用程序设置”页中,选择“附加选项”下的“空项目”。
如果你选择的是VC6.0那么你选择选择MFC AppWizdra(DLL)直接就可以生成
C#调用C++的Dll文件添加[DllImport("CSharpInvokeCPP.CPPDemo.dll")]就可以如果还不清楚可以参考下面
背景
在项目过程中,有时候你需要调用非C#编写的DLL文件,尤其在使用一些第三方通讯组件的时候,通过C#来开发应用软件时,就需要利用DllImport特性进行方法调用。本篇文章将引导你快速理解这个调用的过程。
步骤
1. 创建一个CSharpInvokeCPP的解决方案:

2. 创建一个C++的动态库项目:

3. 在应用程序设置中,选择“DLL”,其他按照默认选项:

最后点击完成,得到如图所示项目:

我们可以看到这里有一些文件,其中dllmain.cpp作为定义DLL应用程序的入口点,它的作用跟exe文件有个main或者WinMain入口函数是一样的,它就是作为DLL的一个入口函数,实际上它是个可选的文件。它是在静态链接时或动态链接时调用LoadLibrary和FreeLibrary时都会被调用。详细内容可以参考(http://blog.csdn.net/benkaoya/archive/2008/06/02/2504781.aspx)。
4. 现在我们打开CSharpInvokeCPP.CPPDemo.cpp文件:
现在我们加入以下内容:
1 // CSharpInvokeCPP.CPPDemo.cpp : 定义 DLL 应用程序的导出函数。
2 //
3
4 #include "stdafx.h"
5
6 extern"C" __declspec(dllexport) int Add(int x, int y)
7 {
8 return x + y;
9 }
10 extern"C" __declspec(dllexport) int Sub(int x, int y)
11 {
12 return x - y;
13 }
14 extern"C" __declspec(dllexport) int Multiply(int x, int y)
15 {
16 return x * y;
17 }
18 extern"C" __declspec(dllexport) int Divide(int x, int y)
19 {
20 return x / y;
21 }
extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。而被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。
__declspec(dllexport)的目的是为了将对应的函数放入到DLL动态库中。
extern "C" __declspec(dllexport)加起来的目的是为了使用DllImport调用非托管C++的DLL文件。因为使用DllImport只能调用由C语言函数做成的DLL。
5. 编译项目程序,最后在Debug目录生成CSharpInvokeCPP.CPPDemo.dll和CSharpInvokeCPP.CPPDemo.lib

我们用反编译工具PE Explorer查看下该DLL里面的方法:

可以发现对外的公共函数上包含这四种“加减乘除”方法。
6. 现在来演示下如何利用C#项目来调用非托管C++的DLL,首先创建C#控制台应用程序:

7. 在CSharpInvokeCSharp.CSharpDemo项目上新建一个CPPDLL类,编写以下代码:
1 publicclass CPPDLL
2 {
3 [DllImport("CSharpInvokeCPP.CPPDemo.dll")]
4 publicstaticexternint Add(int x, int y);
5
6 [DllImport("CSharpInvokeCPP.CPPDemo.dll")]
7 publicstaticexternint Sub(int x, int y);
8
9 [DllImport("CSharpInvokeCPP.CPPDemo.dll")]
10 publicstaticexternint Multiply(int x, int y);
11
12 [DllImport("CSharpInvokeCPP.CPPDemo.dll")]
13 publicstaticexternint Divide(int x, int y);
14 }
DllImport作为C#中对C++的DLL类的导入入口特征,并通过static extern对extern “C”进行对应。
8. 另外,记得把CPPDemo中生成的DLL文件拷贝到CSharpDemo的bin目录下,你也可以通过设置【项目属性】->【配置属性】->【常规】中的输出目录:

这样编译项目后,生成的文件就自动输出到CSharpDemo中了。
9. 然后在Main入口编写测试代码:
1 staticvoid Main(string[] args)
2 {
3 int result = CPPDLL.Add(10, 20);
4 Console.WriteLine("10 + 20 = {0}", result);
5
6 result = CPPDLL.Sub(30, 12);
7 Console.WriteLine("30 - 12 = {0}", result);
8
9 result = CPPDLL.Multiply(5, 4);
10 Console.WriteLine("5 * 4 = {0}", result);
11
12 result = CPPDLL.Divide(30, 5);
13 Console.WriteLine("30 / 5 = {0}", result);
14
15 Console.ReadLine();
16 }
运行结果:

方法得到调用。
10. 以上的方法只能通过静态方法对于C++中的函数进行调用。那么怎样通过静态方法去调用C++中一个类对象中的方法呢?现在我在CPPDemo项目中添加一个头文件userinfo.h:
1 class UserInfo {
2 private:
3 char* m_Name;
4 int m_Age;
5 public:
6 UserInfo(char* name, int age)
7 {
8 m_Name = name;
9 m_Age = age;
10 }
11 virtual~UserInfo(){ }
12 int GetAge() { return m_Age; }
13 char* GetName() { return m_Name; }
14 };
在CSharpInvokeCPP.CPPDemo.cpp中,添加一些代码:
1#include "malloc.h"
2#include "userinfo.h"
3
4typedef struct {
5char name[32];
6int age;
7} User;
8
9UserInfo* userInfo;
10
11extern"C" __declspec(dllexport) User* Create(char* name, int age)
12{
13 User* user = (User*)malloc(sizeof(User));
14
15 userInfo =new UserInfo(name, age);
16 strcpy(user->name, userInfo->GetName());
17 user->age = userInfo->GetAge();
18
19return user;
20}
这里声明一个结构,包括name和age,这个结构是用于和C#方面的结构作个映射。
注意:代码中的User*是个指针,返回也是一个对象指针,这样做为了防止方法作用域结束后的局部变量的释放。
strcpy是个复制char数组的函数。
11. 在CSharpDemo项目中CPPDLL类中补充代码:
1 [DllImport("CSharpInvokeCPP.CPPDemo.dll")]
2 publicstaticextern IntPtr Create(string name, int age);
3
4 [StructLayout(LayoutKind.Sequential)]
5 publicstruct User
6 {
7 [MarshalAs(UnmanagedType.ByValTStr, SizeConst =32)]
8 publicstring Name;
9
10 publicint Age;
11 }
其中这里的结构User就和C++中的User对应。
12. 在Program.cs中补充代码:
1 IntPtr ptr = CPPDLL.Create("李平", 27);
2 <strong><font color="#ff0000">CPPDLL.User user = (CPPDLL.User)Marshal.PtrToStructure(ptr, typeof(CPPDLL.User));</font></strong>
3 Console.WriteLine("Name: {0}, Age: {1}", user.Name, user.Age);
注意:红色字体部分,这里结构指针首先转换成IntPtr句柄,然后通过Marshal.PtrToStructrue转换成你所需要的结构。
运行结果:

将halcon导出的c++程序打包成dll库的更多相关文章
- 将eclipse的应用程序打包成.exe
转自:http://blog.163.com/loveshijie_1991/blog/static/1760553112012102573437156/ 参考:http://blog.csdn.ne ...
- 解析Xcode把应用程序打包成ipa---解决打包完新版本itunes提示不是有效应用程序的问题
Xcode把应用程序打包成ipa是本文要介绍的内容,不多说,先俩看内容.注意:本方法需要先制作假凭证编译于项目中,否则产生的ipa还是无法于iPhone中运行. 制作方法请参考: http://blo ...
- Xcode把应用程序打包成ipa
Xcode把应用程序打包成ipa 分类: App Store2012-11-20 15:47 11722人阅读 评论(0) 收藏 举报 Xcode教程 Xcode4发布测试 打包Archive操作是本 ...
- Visual Studio 2017 - Windows应用程序打包成exe文件(2)- Advanced Installer 关于Newtonsoft.Json,LINQ to JSON的一个小demo mysql循环插入数据、生成随机数及CONCAT函数 .NET记录-获取外网IP以及判断该IP是属于网通还是电信 Guid的生成和数据修整(去除空格和小写字符)
Visual Studio 2017 - Windows应用程序打包成exe文件(2)- Advanced Installer Advanced Installer :Free for 30 da ...
- Java桌面程序打包成exe可执行文件
前言: 我们都知道Java可以将二进制程序打包成可执行jar文件,双击这个jar和双击exe效果是一样一样的,但感觉还是不同.其实将java程序打包成exe也需要这个可执行jar文件. 准备: ecl ...
- Windows服务项目打包成安装包(Windows服务)-----------VS2017项目程序打包成.msi或者.exe
VS2017项目程序打包成.msi或者.exe Windows服务项目使用VS2017项目程序打包成.msi或者.exe安装包 项目打包成安装包(Windows服务) 1.安装打包插件:Microso ...
- VS2017项目程序打包成.msi或者.exe
VS2017项目程序打包成.msi或者.exe 1.安装打包插件:Microsoft Visual Studio 2017 Installer Projects 打开vs2017 ,选择 工具 --& ...
- JAVA程序打包成exe文件详细图解
我们都知道Java可以将二进制程序打包成可执行jar文件,双击这个jar和双击exe效果是一样一样的,但感觉还是不同.其实将java程序打包成exe也需要这个可执行jar文件. 准备: eclipse ...
- Java程序打包成exe可执行文件
前言: 我们都知道Java可以将二进制程序打包成可执行jar文件,双击这个jar和双击exe效果是一样一样的,但感觉还是不同.其实将java程序打包成exe也需要这个可执行jar文件. 准备: ecl ...
随机推荐
- Dom 概览
前言 我们已经接触并使用了很多api去操作html文档,例如:appendChild,getElementById, 等等.但是,每当我在浏览器输入document,window 按下回车,会发现还有 ...
- redux介绍与入门
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Helvetica } p.p2 { margin: 0.0px 0.0px 0.0px 0. ...
- 一个servlet处理多个功能
servlet中: String servletPath = request.getServletPath(); String methodName = servletPath.substring(1 ...
- UGUI text image 等加Shadow OutLine等
Text,文本控件,同NGUI中的Label.支持动态字库.大小调节.富文本(基本的html标签格式)等等.描边.阴影等需要Effect组件支持.Add Component-->UI--> ...
- qq加好友加群限制ip怎么解决
目前各样格式的推广都会用到腾讯QQ,现在就遇到了问题.QQ加好友加群,经常会提示你的账号存在不安全因素,暂停加好友功能.这个原因都是本地同一个IP,登陆的QQ过多,加好友过多.导致这个IP被记录,相当 ...
- js 刷新窗口
在js 方法里面 1.window.opener.location.reload() 刷新父窗口 2.window.location.reload() 该方法强迫浏览器刷新当前 ...
- AWS EC2首次使用VPS
看到AWS有免费一年的试用期,就申请了一个账号.想搭建一个自己的网站.申请之前,你还需要有一张信用卡. 申请AWS账号,登陆控制台 进入AWS官网即可申请账号,进入控制台后,就可以新建一个AWS EC ...
- centos6.5安装node.js
一次偶然的机会知道有nodejs这个东西,确实对它还是很感兴趣的.刚开始只知道它能让javascript写后台,然后前后台都由javascript来写,确实觉得真的挺爽,毕竟人总是喜欢在自己熟悉领域做 ...
- asp.net用户自定义控件传参
asp.net自定义控件传参的方式有2中: ①字段的方式 在自定义控件的.ascx.cs中定义一个字段,然后在调用页面的page_load方法里面传入参数. 如 在自定义控件中设置字段 publ ...
- 3个sprint的团队贡献分
第一次冲刺贡献分 成员名字 贡献分 101丘娟 23 108周诗琦 26 107杨晓霞 24 124陈程 27 第二次冲刺贡献分 成员名字 贡献分 101丘娟 23 108周诗琦 27 ...