目录:

1.非托管方式

2.托管方式

3.介绍 extern "C"

4.介绍   DllImport

1.非托管方式

第一种,非托管方式:调用类和方法https://www.codeproject.com/Articles/18032/How-to-Marshal-a-C-Class

  非托管方式,只能调用函数,并且函数在extern "C"的体里面

  有一下几种方式,把函数都写了,把接口写了。

//创建对象的方法
extern "C" EXAMPLEUNMANAGEDDLL_API CUnmanagedTestClass* CreateTestClass()
{
return new CUnmanagedTestClass();
}
//释放对象
extern "C" EXAMPLEUNMANAGEDDLL_API void DisposeTestClass(CUnmanagedTestClass* pObject)
{
if(pObject != NULL)
{
delete pObject;
pObject = NULL;
}
}
//调用函数
extern "C" EXAMPLEUNMANAGEDDLL_API void CallPassInt(CUnmanagedTestClass* pObject, int nValue)
{
if(pObject != NULL)
{
pObject->PassInt(nValue);
}
}
//调用函数
extern "C" EXAMPLEUNMANAGEDDLL_API void CallPassString(CUnmanagedTestClass* pObject, char* pchValue);
extern "C"{
 EXAMPLEUNMANAGEDDLL_API char* CallReturnString(CUnmanagedTestClass* pObject)
}

C++的调用

  把生成的TestClassDLL.dll放到 bin/Debug/下,然后在C#中调用

public class CSUnmanagedTestClass : IDisposable
{
#region PInvokes
[DllImport("TestClassDLL.dll")]
static private extern IntPtr CreateTestClass(); [DllImport("TestClassDLL.dll")]
static private extern void DisposeTestClass(IntPtr pTestClassObject); [DllImport("TestClassDLL.dll")]
static private extern void CallPassInt(IntPtr pTestClassObject, int nValue);
.
.
.
#endregion PInvokes #region Members
private IntPtr m_pNativeObject;
// Variable to hold the C++ class's this pointer
#endregion Members public CSUnmanagedTestClass()
{
// We have to Create an instance of this class through an exported
// function
this.m_pNativeObject = CreateTestClass();
} public void Dispose()
{
Dispose(true);
} protected virtual void Dispose(bool bDisposing)
{
if(this.m_pNativeObject != IntPtr.Zero)
{
// Call the DLL Export to dispose this class
DisposeTestClass(this.m_pNativeObject);
this.m_pNativeObject = IntPtr.Zero;
} if(bDisposing)
{
// No need to call the finalizer since we've now cleaned
// up the unmanaged memory
GC.SuppressFinalize(this);
}
} // This finalizer is called when Garbage collection occurs, but only if
// the IDisposable.Dispose method wasn't already called.
~CSUnmanagedTestClass()
{
Dispose(false);
} #region Wrapper methods
public void PassInt(int nValue)
{
CallPassInt(this.m_pNativeObject, nValue);
}
.
.
.
#endregion Wrapper methods
}

2.托管方式

我手上有一个C++写的类(NativeClass),想在C#下调用这个类,可是C#是没有简单的像Dllimport这样的方法获取非托管C++ dll里的类。我的解决方法是,生成一个托管C++的dll,然后在C#下引用这个dll。因为托管代码与非托管代码是不能在一个文件里混编的,所以我必须将非托管C++写的NativeClass用托管C++的手段封装一下,然后生成一个dll,以供C#调用。

https://www.cnblogs.com/stemon/p/4246165.html

3.介绍 extern "C"

:https://www.cnblogs.com/xiangtingshen/p/10980055.html

extern "C"包含双重含义

  • 被extern "C"修饰的变量和函数是按照C语言方式进行编译和链接的:这点很重要!!!!
  • extern "C"的使用要点总结

    1,可以是如下的单一语句:

    extern "C" double sqrt(double);

    2,可以是复合语句, 相当于复合语句中的声明都加了extern "C"

    extern "C"
    {
    double sqrt(double);
    int min(int, int);
    }

    3,可以包含头文件,相当于头文件中的声明都加了extern "C" 

extern "C"
{
#include <cmath>
}

  

4.介绍   DllImport

  https://www.cnblogs.com/fer-team/archive/2017/12/13/8033413.html

要使用DllImport需要引用命名空间: System.Runtime.InteropServices;
DllImport 属性定义
如下:

namespace System.Runtime.InteropServices
{
  [AttributeUsage(AttributeTargets.Method)]
  public class DllImportAttribute: System.Attribute
  {
public DllImportAttribute(string dllName){...} //定位参数为dllName
public CallingConvention CallingConvention; //入口点调用约定
public CharSet CharSet; //入口点采用的字符接
public string EntryPoint; //入口点名称
public bool ExactSpelling; //是否必须与指示的入口点拼写完全一致,默认false
public bool PreserveSig; //方法的签名是被保留还是被转换
public bool SetLastError; //FindLastError方法的返回值保存在这里
public string Value {get {...}}
  }
}

说明:
1、DllImport只能放置在方法声明上。
2、DllImport具有单个定位参数:指定包含被导入方法的 dll 名称的 dllName 参数。
3、DllImport具有五个命名参数:
a、CallingConvention 参数指示入口点的调用约定。如果未指定CallingConvention,则使用默认值CallingConvention.Winapi。
b、CharSet参数指定用在入口点的字符集。如果未指定CharSet,则使用默认值CharSet.Auto。
c、EntryPoint参数给出dll中入口点的名称。如果未指定EntryPoint,则使用方法本身的名称。
d、ExactSpelling参数指示EntryPoint是否必须与指示的入口点的拼写完全匹配。如果未指定ExactSpelling,则使用默认值false。
e、PreserveSig参数指示方法的签名被保留还是被转换。当签名被转换时,它被转换为一个具有HRESULT返回值和该返回值的一个名为retval的附加输出参数的签名。如果未指定PreserveSig,则使用默认值true。
f、SetLastError参数指示方法是否保留Win32“上一错误”。如果未指定SetLastError,则使用默认值false。
4、它是一次性属性类。
5、用DllImport属性修饰的方法必须具有extern修饰符。

C# 调用 C++ dll的两种方式的更多相关文章

  1. C#动态调用WCF接口,两种方式任你选。

    写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触到现在断断续续,真正使用的项目少之又少,更谈不上深入WCF内部实现机制和原理去研究,最近自己做一个项目时用到了WCF. 从这 ...

  2. SoapUI调用webservice实现的两种方式

    SoapUI用来做测试,已经是很多人做过的事情了,而且网上教程也很多.不过还是写下来,对比webservice协议与http协议脚本编写的不同. 首先测接口得有一个服务,刚好笔者所在项目做ESB集成. ...

  3. C++调用C代码的两种方式

    由于C++支持函数重载,在编译函数代码的时候会加上参数类型的信息,而C编译只有函数名信息,导致C++直接调用C代码在链接的时候会出现函数未定义的问题.解决这种问题有两种方法.方法一:在写C代码的时候考 ...

  4. Delphi 调用Dll的两种方式

    unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  5. vc导出调用dll的两种方式

    一.stdcall 1. #define  DLLEXPORT _declspec(dllexport) _stdcall, int DLLEXPORT func(const char *peer,u ...

  6. javascript消除字符串两边空格的两种方式,面向对象和函数式编程。python oop在调用时候的优点

    主要是javascript中消除字符串空格,比较两种方式的不同 //面向对象,消除字符串两边空格 String.prototype.trim = function() { return this.re ...

  7. 在基于MVC的Web项目中使用Web API和直接连接两种方式混合式接入

    在我之前介绍的混合式开发框架中,其界面是基于Winform的实现方式,后台使用Web API.WCF服务以及直接连接数据库的几种方式混合式接入,在Web项目中我们也可以采用这种方式实现混合式的接入方式 ...

  8. WCF 客户端调用服务操作的两种方法

    本节的主要内容:1.通过代理类的方式调用服务操作.2.通过通道的方式调用服务操作.3.代码下载 一.通过代理类的方式调用服务操作(两种方式添加代理类) 1.手动编写代理类,如下: 客户端契约: usi ...

  9. java中调用本地动态链接库(*.DLL)的两种方式详解和not found library、打包成jar,war包dll无法加载等等问题解决办法

    我们经常会遇到需要java调用c++的案例,这里就java调用DLL本地动态链接库两种方式,和加载过程中遇到的问题进行详细介绍 1.通过System.loadLibrary("dll名称,不 ...

随机推荐

  1. jenkins使用--安装文档

    添加Jenkins的源(repository): #sudo wget -O /etc/yum.repos.d/jenkins.repo http://jenkins-ci.org/redhat/je ...

  2. 刷题记录:[强网杯 2019]Upload

    目录 刷题记录:[强网杯 2019]Upload 一.知识点 1.源码泄露 2.php反序列化 刷题记录:[强网杯 2019]Upload 题目复现链接:https://buuoj.cn/challe ...

  3. linux 下查看redis是否启动

    make make PREFIX=/usr/local/redis install mkdir /etc/redis/ cp redis.conf /etc/redis/ 打开redis.conf文件 ...

  4. 【转载】 TensorFlow函数:tf.Session()和tf.Session().as_default()的区别

    原文地址: https://blog.csdn.net/Enchanted_ZhouH/article/details/77571939 ------------------------------- ...

  5. DSCP 标

    DSCP差分服务代码点(Differentiated Services Code Point).它在每个数据包IP头部的服务类别TOS标识字节中,利用已使用的6比特和未使用的2比特,通过编码值来区分优 ...

  6. Ubuntu16.04下配置VScode的C/C++开发环境

    博客转载:https://blog.csdn.net/weixin_43374723/article/details/84064644 Visual studio code是微软发布的一个运行于 Ma ...

  7. Cassandra开发入门文档第一部分

    Cassandra的特点 横向可扩展性: Cassandra部署具有几乎无限的存储和处理数据的能力.当需要额外的容量时,可以简单地将更多的机器添加到集群中.当新机器加入集群时,Cassandra需要对 ...

  8. jw python 培训帮助 手册

    #########sample 1  (如果python 遇到有问题,就求助于 help 命令,python 是 个人开发的胶水语言,因此不具备 java,c++的类的继承关系) Python hel ...

  9. .net core 2.2 EF oracle db first

    Nuget控制台: Install-Package log4net Install-Package Newtonsoft.Json Install-Package Autofac Install-Pa ...

  10. 【并行计算-CUDA开发】OpenACC与OpenHMPP

    在西雅图超级计算大会(SC11)上发布了新的基于指令的加速器并行编程标准,既OpenACC.这个开发标准的目的是让更多的编程人员可以用到GPU计算,同时计算结果可以跨加速器使用,甚至能用在多核CPU上 ...