首页 > 编程语言 >《dll篇》c#调用c++dll

《dll篇》c#调用c++dll

时间:2023-08-01 14:23:51浏览次数:44  
标签:Function 调用 c# c++ DLL int C++ dll

c#调用c++dll

参考链接:https://jingyan.baidu.com/article/5d6edee2da72d699eadeecfe.html

生成dll

环境:VS2008

新建项目->Visual C++->Win32项目 MyDLL

注意:C++编写的dll一般是不能直接拿来C#调用,需要先新建个C++的工程把dll里的方法重新封装成可被C#外部调用的函数。

image

image

MyDLL.cpp里的代码如下:

extern "C"  _declspec(dllexport)int add(int a ,int b)

{

int sum=a+b;

return sum;

}

注意:函数前一定要加

extern "C"  _declspec(dllexport),

可被外部引用

项目->属性->常规->公共语言运行库支持->公共语言运行库支持(/clr)

image

F5编译程序,在Debug文件夹中找到生成MyDLL.dll目标文件备用

引用dll

新建项目->Visual C#->控制台应用程序 dllConsoleApplication1

image

将步骤1生成的MyDLL.dll文件copy到dllConsoleApplication1工程的根目录下

image

Program.cs代码如下

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.InteropServices;   //必须添加,不然DllImport报错

namespace dllConsoleApplication1

{

	class CPPDLL

	{

		[DllImport("MyDLL.dll", CharSet = CharSet.Ansi)] //引入dll,并设置字符集

		public static extern int add(int a ,int b);

	}

	class Program

	{

		static void Main(string[] args)

		{

			int sum=CPPDLL.add(3, 4);

		}

	}

}

编译程序,在程序中加断点,查看函数的计算结果

image

到这里,C++dll里的方法已经在C#里调用成功了。

如果你的C++dll里还调用了其他的dll文件那么需要把调用的其他dll文件也加到C#工程的根目录里,不然就会报错找不到MyDLL.dll模块。

c#调用c++dll法2

参考链接:https://www.jb51.net/article/247558.htm

介绍

C#是托管型代码,创建的对象会自动回收。C++是非托管型代码,创建的对象需要手动回收(有时不手动回收,可能出现内存溢出的问题)。

C#调用C++的方式分为两种:(1)采用托管的方式进行调用;(2)非托管的方式进行调用。

托管方式

采用托管的方式进行调用,就和正常调用c#的dll一样

创建新的c++项目

image

Function.h中的代码,一个返回两数之和的方法,一个返回字符串的方法

#pragma once
#include <string>
public ref class Function
{
public:
	Function(void);
	~Function(void);
	int menber;
	int menberFuncAdd(int a,int b);
	System::String^ say(System::String^ str);
};

//.cpp
#include "Function.h"
Function::Function(void)
{
}
Function::~Function(void)
{
}

int Function::menberFuncAdd(int a,int b)
{
   return a+b;
}
System::String^ Function::say(System::String^ str)
{
   return str;
}

Function.h中空白不用写

#include "Function.h"

注意:c++的项目一定要选择公共语言运行时支持

image

在c#的项目中像引用c#的dll一样引用

image

代码中调用

image

Function fun = new Function();
		   int a = fun.menberFuncAdd(1, 2);
		   string s = fun.say("Hello World");

注意:c#项目一定要选择x86,否则要报错。

image

运行效果:

image

非托管

创建新的c++项目

image

stdafx.h中的代码

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"
#ifdef A_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
#define WIN32_LEAN_AND_MEAN             //  从 Windows 头文件中排除极少使用的信息
// Windows 头文件:
#include <windows.h>

extern "C" DLL_API void MessageBoxShow();

// TODO: 在此处引用程序需要的其他头文件

dllmain.cpp中的代码

#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
					   DWORD  ul_reason_for_call,
					   LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

#ifdef _MANAGED
#pragma managed(push, off)
#endif

void MessageBoxShow()
{
	MessageBox(NULL, TEXT("Hello World"), TEXT("In a DLL"), MB_OK);
}


#ifdef _MANAGED
#pragma managed(pop)
#endif

注意:c++的项目一定要选择公共语言运行时支持

image

在代码加上

[DllImport("ll.dll")]
 public extern static void MessageBoxShow();

image

注意:c#项目一定要选择x86,否则要报错。

image

运行结果:

image

报错无法加载DLL,找不到指定模块

参考文档:cnblogs.com/yxzstruggle/p/16172138.html

image

1.DLL文件夹放置位置:

(1)将缺少的DLL放到项目文件夹下的“/bin/bebug“

(2)系统文件夹下的”C:/WINDOWS/system32“

如果确定位置是正确的,那么就有可能是调用的DLL文件还用到了其他DLL文件中的内容,这很关键。可以通过下载Dependency Walker (depends.exe) Home Page查看缺少哪些dll库。

例如博主在调用C++封装的DLL时就报错,最后发现是需要安装C++运行环境,这个问题可通过安装”VC++ 运行库“来解决。

还有一种是在发布程序时,可能会缺少wpf的环境,例如”.NET Framework 4.6.1“只需要下载下来安装就可以了。

报错试图加载格式不正确的程序

参考链接:https://blog.csdn.net/songyi160/article/details/51354660

程序在32位操作系统上运行正常,在64位操作系统上运行读卡功能提示”试图加载格式不正确“。

出错原因:因为'任何 CPU'编译运行的程序在64位的机器上就会用运行为64位,而64位程序是不能加载32位dll的

解决方法:项目右键属性->项目设计器->生成->平台->把'默认设置(任何 CPU)'改为x86。

标签:Function,调用,c#,c++,DLL,int,C++,dll
From: https://www.cnblogs.com/fusio/p/17596327.html

相关文章

  • [React] forwardRef typescript
    importReact,{forwardRef}from"react";//DeclareatypethatworkswithgenericcomponentstypeFixedForwardRef=<T,P={}>(render:(props:P,ref:React.Ref<T>)=>React.ReactElement)=>(props:P&React.RefAttri......
  • GO 编程模式:FUNCTIONAL OPTIONS
    在本篇文章中,我们来讨论一下FunctionalOptions这个编程模式。这是一个函数式编程的应用案例,编程技巧也很好,是目前在Go语言中最流行的一种编程模式。但是,在我们正式讨论这个模式之前,我们需要先来看看要解决什么样的问题。本文是全系列中第3/10篇:Go编程模式Go编程模式:切片,接口......
  • CGLIB动态代理对象GC问题排查
    一、问题是怎么发现的最近有个新系统开发完成后要上线,由于系统调用量很大,所以先对核心接口进行了一次压力测试,由于核心接口中基本上只有纯内存运算,所以预估核心接口的压测QPS能够达到上千。压测容器配置:4C8G先从10个并发开始进行发压,结果cpu一下就飙升到了100%,但是核心接口的qp......
  • CCIA数安委等组织发起“个人信息保护影响评估专题工作”,合合信息首批入选试点
    近期,“个人信息保护影响评估专题工作”(简称“PIA专题工作”)试点评估结果正式发布。PIA专题工作组由中国电子技术标准化研究院、中国信息通信院等单位的法律与技术专家组成,对试点申报单位开展PIA工作的过程是否符合评估依据提出的原则、框架、方法等进行评价,百度、快手、抖音、阿维......
  • Tomcat9 无法启动组件[Connector[AJP/1.3-8009]]
    无法启动组件[Connector[AJP/1.3-8009]]在tomcat中开启ajp后,启动tomcat遇到错误无法启动组件[Connector[AJP/1.3-8009]]。错误原因缺少配置项secretRequired。tomcat9提供的默认的AJP配置如下:<Connectorprotocol="AJP/1.3"address="::1"port="800......
  • Branch端口操作指南
    近期的版本升级中,我们的开发团队对Branch端口进行了优化改进。本文将使用最新的知行之桥2023-23.2.8605.0版本,为大家展开介绍。Branch端口概览使用场景:多种业务类型文件分类时,级联使用。端口功能:配置确定要查找的值以及要比较的目标值。如果传入值与目标值匹配,则消息将沿......
  • DC电源模块输出电压的调节范围
    BOSHIDADC电源模块输出电压的调节范围DC电源模块是一种可以将交流电转换为直流电的设备,可以广泛应用于电子、通信、工业自动化等领域。在实际使用中,输出电压的调节范围非常重要,因为它决定了该模块能够适应的电器设备的种类和使用范围。下面将详细介绍DC电源模块输出电压的调节范......
  • HA在OceanBase中的应用
    上一篇文章中我们讨论了《OceanBase中主备Rootserver如何管理切换》,里面最机要的一部分就是HA。OceanBase中使用了这两个软件来搭建HA环境:corosync+pacemakerHA所做的工作简单来说就是当发现主机不可用时自动把VIP切换到备机。如何使用这两个软件来搭建主备集群的详细文......
  • 发电站乐队歌词全中译 / The Comprehensive Chinese Translation of Kraftwerk Lyrics
    发电站乐队歌词全中译/TheComprehensiveChineseTranslationofKraftwerkLyrics发电站所有英文版录音室专辑的歌词中文翻译。《TheMix》和《Minimum-Maximum》为重混(remix)或演唱会专辑,故《Expo2000》和《PlanetofVisions》单列,其它单曲的歌词并入其它专辑中,作为某首歌......
  • DecimalFormat格式化数据.00问题
    废话不多说,直接上代码publicvoiddecimalFormat(){DecimalFormatdf=newDecimalFormat("#.00");Stringformat=df.format(Double.valueOf("9.00"));System.out.println(format);}优化方式publicvoiddecimalFormat(){DecimalFormatdf......