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库的更多相关文章

  1. 将eclipse的应用程序打包成.exe

    转自:http://blog.163.com/loveshijie_1991/blog/static/1760553112012102573437156/ 参考:http://blog.csdn.ne ...

  2. 解析Xcode把应用程序打包成ipa---解决打包完新版本itunes提示不是有效应用程序的问题

    Xcode把应用程序打包成ipa是本文要介绍的内容,不多说,先俩看内容.注意:本方法需要先制作假凭证编译于项目中,否则产生的ipa还是无法于iPhone中运行. 制作方法请参考: http://blo ...

  3. Xcode把应用程序打包成ipa

    Xcode把应用程序打包成ipa 分类: App Store2012-11-20 15:47 11722人阅读 评论(0) 收藏 举报 Xcode教程 Xcode4发布测试 打包Archive操作是本 ...

  4. 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 ...

  5. Java桌面程序打包成exe可执行文件

    前言: 我们都知道Java可以将二进制程序打包成可执行jar文件,双击这个jar和双击exe效果是一样一样的,但感觉还是不同.其实将java程序打包成exe也需要这个可执行jar文件. 准备: ecl ...

  6. Windows服务项目打包成安装包(Windows服务)-----------VS2017项目程序打包成.msi或者.exe

    VS2017项目程序打包成.msi或者.exe Windows服务项目使用VS2017项目程序打包成.msi或者.exe安装包 项目打包成安装包(Windows服务) 1.安装打包插件:Microso ...

  7. VS2017项目程序打包成.msi或者.exe

    VS2017项目程序打包成.msi或者.exe 1.安装打包插件:Microsoft Visual Studio 2017 Installer Projects 打开vs2017 ,选择 工具 --& ...

  8. JAVA程序打包成exe文件详细图解

    我们都知道Java可以将二进制程序打包成可执行jar文件,双击这个jar和双击exe效果是一样一样的,但感觉还是不同.其实将java程序打包成exe也需要这个可执行jar文件. 准备: eclipse ...

  9. Java程序打包成exe可执行文件

    前言: 我们都知道Java可以将二进制程序打包成可执行jar文件,双击这个jar和双击exe效果是一样一样的,但感觉还是不同.其实将java程序打包成exe也需要这个可执行jar文件. 准备: ecl ...

随机推荐

  1. 使用Gson转换json数据为Java对象的一个例子

    记录工作中碰到的一个内容. 原料是微信平台的一个接口json数据. { "errcode" : 0, "errmsg" : "ok", &q ...

  2. Web开发中20个很有用的CSS库

    来源: 微信公众号文章 在过去的几年中,CSS已经成为一大部分开发者和设计者的最爱,因为它提供了一系列功能和特性.每个月都有无数个围绕CSS的工具被开发者发布以简化WEB开发.像CSS库,框架,应用这 ...

  3. Java项目JUnit简单使用

    前面自己写了一个计算器,准备用在项目里 http://www.cnblogs.com/blog5277/p/5707304.html 由于项目是用户计算跟钱有关的,所以这可不敢出BUG 于是就用了JU ...

  4. 使用Yii框架完整搭建网站流程入门

    下载地址: http://www.yiiframework.com/ http://www.yiichina.com/ 由美籍华人薛强研究而出, Yii 这个名字(读作易(Yee))代表 简单(eas ...

  5. python 3次登录

    #!/usr/bin/env python #-*- encoding: utf- -*- import sys import os import getpass import platform # ...

  6. linux系统下静态IP的设置

    首先说明:下面用的系统为:kali 4.6.0版本的哦:不同的系统是不一样的:反正吧,在ubuntu上的好多方法在kali上就不管用,并且吧,不同的ubuntu的版本也不一样的: 第一步:设置网络的I ...

  7. ssm+redis 如何更简洁的利用自定义注解+AOP实现redis缓存

    基于 ssm + maven + redis 使用自定义注解 利用aop基于AspectJ方式 实现redis缓存 如何能更简洁的利用aop实现redis缓存,话不多说,上demo 需求: 数据查询时 ...

  8. 【java基础】面向对象的三大基本特征之-------继承

    面向对象的三大特征:封装,继承,多态 java通过extends关键字来实现继承,而且是单继承,一个子类只可以有一个直接父类,但是父类还可以有父类... java.long.Object是所有类的父类 ...

  9. Head First 设计模式 --11 代理模式

    代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问. 代码: interface Boss { public void meeting(); } class BossImp implem ...

  10. nginx配合zabbix编译安装时web下一步跳转问题

    很多时候编译安装的时候把zabbix的php包拷贝到web所在目录之后(本文为nginx所在html目录),网页打开http:/localhost/zabbix却进不去下图: 或者是点了下一步没反应, ...