综述 : 本文章介绍.Net 环境下C# 通过托管C++调用本地C++ Dll文件, 示例环境为:VS2010, .Net4.0, Win7. 具体事例为测试C++, C#, 及C#调用本地C++Dll文件进行浮点运算效率的一部分. 如果需要查看三者的效率, 请继续阅读下面的文章.

a 创建本地CPP类库

1. 创建本地CPP的Dll ---->EfficiencyNativeCPPDLL

2. 点击下一步 注意选择为DLL(D)项, 然后选择完成.

3.书写DLL文件

3.1

EfficiencyNativeCppDll.h

#pragma once

#ifndef GoWin_DLL_CLASS_EXPORTS
//该类可导出
#define GoWin_DLL_CLASS __declspec(dllexport)
#else
//该类可导入
#define GoWin_DLL_CLASS __declspec(dllimport)
#endif
#define NPARTS 1000
#define DIMS 3 class GoWin_DLL_CLASS EfficiencyNativeCppDll
{
public:
EfficiencyNativeCppDll(void);
~EfficiencyNativeCppDll(void); void InitPositions();
void UpdatePositions();
double ComputePot();
double Pot;
private:
double _r[DIMS][NPARTS];
};

3.2

EfficiencyNativeCppDll.cpp

#define WIN32_LEAN_AND_MEAN             //  从 Windows 头文件中排除极少使用的信息
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h> EfficiencyNativeCppDll::EfficiencyNativeCppDll(void)
{
Pot = 0;
} EfficiencyNativeCppDll::~EfficiencyNativeCppDll(void)
{
printf("~EfficiencyNativeCppDll is called");
} void EfficiencyNativeCppDll::InitPositions()
{
for(int i = 0; i < DIMS; i++)
{
for (int j = 0; j < NPARTS; j++)
{
_r[i][j] = 0.5 + (double)rand()/RAND_MAX;
}
}
} void EfficiencyNativeCppDll::UpdatePositions()
{
for(int i = 0; i < DIMS; i++)
{
for (int j = 0; j < NPARTS; j++)
{
_r[i][j] -= 0.5 + (double)rand()/RAND_MAX;
}
}
} double EfficiencyNativeCppDll::ComputePot()
{
double distx, disty, distz, dist;
double pot;
distx = 0;
disty = 0;
distz = 0;
pot = 0; for(int i=0; i<NPARTS; i++ )
{
for(int j=0; j<i-1; j++ )
{
distx = pow( (_r[0][j] - _r[0][i]), 2 );
disty = pow( (_r[1][j] - _r[1][i]), 2 );
distz = pow( (_r[2][j] - _r[2][i]), 2 );
dist = sqrt( distx + disty + distz );
pot += 1.0 / dist;
}
} this->Pot = pot; return pot;
}

在Release状态下生成, 会得到 EfficiencyNativeCPPDLL.dll 和 EfficiencyNativeCPPDLL.lib两种文件 其中EfficiencyNativeCPPDLL.dll用于后面的CLR/C++调用; 而EfficiencyNativeCPPDLL.lib则用于Native C++的调用; 这在效率对比一文中会用到.

b 创建C++/CLI类库

1. 添加新建项目 EfficiencyCLRWrapper

2. 项目 EfficiencyCLRWrapper需要对项目EfficiencyNativeCPPDLL中的EfficiencyNativeCppDll.h 和 EfficiencyCLRWrapper.dll引用

2.1 引用EfficiencyNativeCppDll.h

有两种方式, 可任选一种

a) 将EfficiencyNativeCppDll.h直接复制到 项目 EfficiencyCLRWrapper中, 这很简单 不再描述

b)  更改 项目 EfficiencyCLRWrapper属性设置中包换目录选项, 以包含文件EfficiencyNativeCppDll.h

b.1) 看到右侧的包含目录了吗? 点击后选择 编辑

b.2)   我这里选择了把EfficiencyNativeCPPDLL文件夹及项目EfficiencyNativeCPPDLL的Release文件夹均包含在内了

2.2 引用完成后书写C++/CLR代码

2.2.1 头文件

EfficiencyCLRWrapper.h

#pragma once
#include "EfficiencyNativeCppDll.h"
#define GoWin_DLL_CLASS using namespace System; namespace EfficiencyCLRWrapper { public ref class CLRWrapper
{
private:
EfficiencyNativeCppDll * _pNtvCppPro;
public:
CLRWrapper(void);
~CLRWrapper(void);
void InitPositions();
void UpdatePositions();
double ComputePot();
property double Pot
{
double get();
void set(double value);
}
};
}

2.2.2 主体文件

#include "EfficiencyCLRWrapper.h"
using namespace EfficiencyCLRWrapper; CLRWrapper::CLRWrapper(){ this->_pNtvCppPro = new EfficiencyNativeCppDll();}
CLRWrapper::~CLRWrapper(){} double CLRWrapper::ComputePot()
{
return this->_pNtvCppPro->ComputePot();
} void CLRWrapper::InitPositions()
{
this->_pNtvCppPro->InitPositions();
} void CLRWrapper::UpdatePositions()
{
this->_pNtvCppPro->UpdatePositions();
} double CLRWrapper::Pot::get()
{
return this->_pNtvCppPro->Pot;
} void CLRWrapper::Pot::set(double value)
{
this->_pNtvCppPro->Pot = value;
}

2.2.3 将形成如下树结构:

3. 千万不要忘记的一点就是在项目EfficiencyCLRWrapper中对EfficiencyNativeCPPDLL的引用, 否则依旧无法生成, 如图:

4 这个时候 对项目EfficiencyCLRWrapper在Release下生成则可以得到 文件 CLRCPPWrapper.dll

C 创建C# 控制台应用程序

1 添加C#项目 ConsoleEfficiencyCSInvokeCLRDll

2.  添加对项目 EfficiencyCLRWrapper的引用
     

3. 因项目ConsoleEfficiencyCSInvokeCLRDll须间接调用EfficiencyNativeCPPDLL.dll因此 跟上面相同可用两种方法解决

可任选其一

a) 将以生成的EfficiencyNativeCPPDLL.dll复制到项目ConsoleEfficiencyCSInvokeCLRDll的bin/Release文件夹下 不再具体描述

b) 添加项目ConsoleEfficiencyCSInvokeCLRDll属性中调试中的工作目录 如图:

4.  在Program.cs文件中做CS的调用

namespace EfficiencyCSInvokeCLRDll
{
class Program
{
static void Main(string[] args)
{
CLRWrapper provider = new CLRWrapper();
const int NITER = 201; provider.InitPositions();
provider.UpdatePositions(); int start = Environment.TickCount;
for (int i = 0; i < NITER; i++)
{
provider.Pot = 0.0; //低效模式
/*provider.ComputePot();
if (i % 10 == 0)
Console.WriteLine("{0}: Potential: \t {1}", i, provider.Pot());
*/ //高效模式
if (i % 10 == 0)
Console.WriteLine("{0}: Potential: \t {1}", i, provider.ComputePot());
provider.UpdatePositions(); }
int stop = Environment.TickCount; Console.WriteLine("Seconds = {0,10}", (double)(stop - start) / 1000); Console.ReadKey();
}
}
}

运行结果:

结果一般在0.240至00.281之间

硬件环境:  Inter(R) Core(TM)2 Duo CPU P8700 @ 2.53GHz 2.53GHz RAM 共4G(2.46GB可用)

疑问:

这里面有两点疑问

1. 在CS调用中标出的高效模式和低效模式; 无非一个是直接调用函数返回值一个是调用函数后读取属性, 但是执行效率相差接近10倍.

2. 在C++/CLR中红色表示的构造函数中申请的内存不晓得何时释放.

.Net 环境下C# 通过托管C++调用本地C++ Dll文件的更多相关文章

  1. $ npm install opencv ? 你试试?! 在windows环境下,使用node.js调用opencv攻略

    博主之前写过一篇文章<html5与EmguCV前后端实现——人脸识别篇>,叙述的是opencv和C#的故事.最近在公司服务器上更新了一套nodejs环境,早就听闻npm上有opencv模块 ...

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

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

  3. win10环境下使用苹果虚拟机不要开多线程应用下载文件

    win10环境下使用苹果虚拟机开多线程应用下载文件时候卡死,网络老掉. 8GB内存不够用?2.5mb网速不够用? 开的百度网盘下载个电影 结果虚拟机卡的不行 关了 网盘 挂起虚拟机 然后再 继续运行客 ...

  4. Centos7环境下使用Nginx托管.Net Core应用程序

    一.安装.Net Core 参考官方文档:https://www.microsoft.com/net/core#linuxcentos 1.添加dotnet产品Feed 在安装.NET Core之前, ...

  5. LNMP环境下独立安装Mysql5.7.18 并对数据库文件进行本地物理迁移 (需暂停数据库服务方式)

    前几天读研时候的同学要我帮忙给解决一个问题,就是Redhat服务器下面安装了LNMP,并且由于分区的划分不当导致MySQL数据库中存放数据库的盘区内空间被急剧消耗,由于该应用主要是数据分析及备份所用, ...

  6. ffi模块——node调用动态链接库(.so/.dll文件)

    参考资料1:[https://www.npmjs.com/package/ffi] 参考资料2:[http://imweb.io/topic/57732fbef0a5487b05f325bf] 参考资 ...

  7. iOS 在 ARC 环境下 dealloc 的使用、理解误区

    iOS 在 ARC 环境下 dealloc 的使用.理解误区 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&qu ...

  8. Linux环境下编译并执行ava helloworld程序

    原文:http://blog.lupaworld.com/home-space-uid-24466-do-blog-id-2578.html 已经学会怎样在Windows下怎样编辑,编译和运行Java ...

  9. nodejs 修改端口号 process.env.PORT(window环境下)

    各个环境下,nodejs设置process.env.PORT的值的命令,如下1.linux环境下: PORT= node app.js 使用上面命令每次都需要重新设置,如果想设置一次永久生效,使用下面 ...

随机推荐

  1. Linux - 用户操作

    常用命令 users # 显示所有的登录用户 groups # 列出当前用户和他所属的组 who -q # 显示所有的登录用户 groupadd # 添加组 useradd user # 建立用户 p ...

  2. 【ORACLE】创建表空间

    CREATE TABLESPACE dna36 DATAFILE 'D:\oracle\oradata\orcl\dna36.dbf' SIZE 100M AUTOEXTEND ON NEXT 10M ...

  3. innodb和myisam数据库文件存储详解以及mysql表空间

    数据库常用的两种引擎有Innodb和Myisam,关于二者的区别参考:https://www.cnblogs.com/qlqwjy/p/7965460.html 1.关于数据库的存储在两种引擎的存储是 ...

  4. 【C语言】十六进制形式输出应用程序

    1.前言 最近在看到同事写了一款封印病毒的程序,非常有意思!原理大致是将PE文件中的ASCII转换成HEX输出到文本中.这样做的目的是为了保存病毒样本的时候不会被杀毒软件查杀!然而却是delphi写的 ...

  5. JVM(3)对象A和B循环引用,最后会不会不被GC回收?-------关于Java的GC机制

    ①首先说一下,GC里边在JVM其中是使用的ROOT算法,ROOT算法,什么称作为ROOT呢,就是说类的静态成员,静态成员就是static修饰的那种,是"根"的一个,根还包含方法中的 ...

  6. html复习之标签整理

    <body>标签,网页上显示的内容放在这里开始学习<p>标签,添加段落<hx>标签,为网页添加标题加入强调语气,使用<strong>加粗和<em& ...

  7. Python发送邮件:smtplib、sendmail

    本地Ubuntu 18.04,本地Python 3.6.5, 阿里云Ubuntu 16.04,阿里云Python 3.5.2, smtplib,sendmail 8.15.2, 今天,打算实现通过电子 ...

  8. MXNet深度学习库简介

    MXNet深度学习库简介 摘要: MXNet是一个深度学习库, 支持C++, Python, R, Scala, Julia, Matlab以及JavaScript等语言; 支持命令和符号编程; 可以 ...

  9. idea中搜狗输入法不跟随光标,看不到输入的字

    好久没在windows上开发了,今天遇到一个比较坑的问题: 最新版idea,输入法都是最新的;但是idea里面输入字,看不到自己输入的是什么字,好坑... 在外面可以看到输入什么字说明与输入法无关, ...

  10. 使用BigDecimal转换较长小数时候出现科学计数法的问题

    public static String divToString(double v1, double v2, int scale){ if (scale < 0) { throw new Ill ...