目录:

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. SpringBoot之KindEditor文件上传

    后端核心代码如下: package com.blog.springboot.controller; import java.io.BufferedOutputStream; import java.i ...

  2. 源码编译Redis Desktop Manager ---(转载)

    精美文章转载: 版权声明:本文作者为「Kany.Wang」,本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议.转载请注明出处!原文链接:https://kany.me/20 ...

  3. 【C++】C++中重载运算符和类型转换

    输入输出运算符 输入输出运算符 输入输出运算符 算术和关系运算符 相等运算符 关系运算符 赋值运算符 复合赋值运算符 下标运算符 递增和递减运算符 成员访问运算符 函数调用运算符 lambda是函数对 ...

  4. TortoiseSVN is locked in another working copy

    TortoiseSVN提交报错 TortoiseSVN is locked in another working copy原因:可能是因为打开了多个commit会话,然后又去修改了提交文件的内容,导致 ...

  5. Mac下iTerm2使用

    之前一直使用 Mac OS 自带的终端,用起来虽然有些不太方便,但总体来说还是可以接受的,是有想换个终端的想法,然后今天偶然看到一个终端利器 iTerm2,发现真的很强大,也非常的好用,按照网上配置了 ...

  6. 爬虫中采集动态HTML介绍

    JavaScript JavaScript 是网络上最常用也是支持者最多的客户端脚本语言.它可以收集 用户的跟踪数据,不需要重载页面直接提交表单,在页面嵌入多媒体文件,甚至运行网页游戏. 我们可以在网 ...

  7. Python3基础 tuple 使用通配符*进行拆包 简单示例

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...

  8. 006-nginx.conf详解-error_page 使用

    一.概述 nginx指令error_page的作用是当发生错误的时候能够显示一个预定义的uri 1.1.使用步骤 更改nginx.conf在http定义区域加入: proxy_intercept_er ...

  9. C++ vector使用实例

    C++ vector #include <iostream> #include <vector> #include <string> #include <al ...

  10. Linux命令-nohup和&

    基础 在linux终端或控制台上执行命令时,可能不希望脚本占住屏幕需要在后台执行脚本,有几种方法让脚本在后台执行: & 当在前台运行某个作业时,终端被该作业占据:可以在命令后面加上& ...