将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 ...
随机推荐
- 腾讯云>>云通信>>TLS后台API在mac上JAVA DEMO搭建
1.相关文档地址 2.相关demo代码 代码部分作了修改,使用了commons-io中的IOUtils.toString简化了io操作 public class Demo { public stati ...
- 24. Swap Nodes in Pairs
24. Swap Nodes in Pairs Given a linked list, swap every two adjacent nodes and return its head. For ...
- Python之路 day2 集合的基本操作
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author:ersa ''' #集合是无序的 集合的关系测试, 增加,删除,查找等操作 ''' #列表去重 ...
- MySQL TCL 整理
TCL(Transaction Control Language)事务控制语言SAVEPOINT 设置保存点ROLLBACK 回滚SET TRANSACTION
- js控制 input框中输入数字时,累计求和
$('.cc input').bind('input propertychange', function(){ var total = 0; $("input").each(fun ...
- SPSS数据分析—二分类Logistic回归模型
对于分类变量,我们知道通常使用卡方检验,但卡方检验仅能分析因素的作用,无法继续分析其作用大小和方向,并且当因素水平过多时,单元格被划分的越来越细,频数有可能为0,导致结果不准确,最重要的是卡方检验不能 ...
- SSH遇见的问题
Gtk-WARNING **: cannot open display: 在从bitbucket仓库向linux服务器clone项目的时候出现了一个问题: ): Gtk-WARNING **: can ...
- Asp.net的request类
ASP.NET获取客户端信息,暂时就这几个,有待添加~~ 1. 在ASP.NET中专用属性: 获取服务器电脑名:Page.Server.ManchineName 获取用户信息:Page.User 获取 ...
- python简介和入门
一.什么是python? python是一种面向对象.解释型的计算机语言,它的特点是语法简洁.优雅.简单易学. 二.解释型语言和编译型语言 编译型语言--就是先把写好的程序翻译成计算机语言然后执行,就 ...
- acm系统开发笔记
时间: 2016/2/29 遇到的困难: 数据库配置的mysql和java(Date)不一致,出现下面错误 Date date = new Date(); SimpleDateFormat ...