zoukankan      html  css  js  c++  java
  • C# 调用 C++ dll的两种方式

     https://www.cnblogs.com/xuqp/p/11987707.html

     

    目录:

    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" 

    1
    2
    3
    4
    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修饰符。

     
  • 相关阅读:
    VC 常见问题百问
    python windows 环境变量
    Check server headers and verify HTTP Status Codes
    Where are the AES 256bit cipher suites? Please someone help
    outlook 如何预订会议和会议室
    安装Axis2的eclipse插件后,未出现界面
    windows 环境变量
    python 时间日期处理汇集
    openldap学习笔记(使用openldap2.3.32)
    set p4 environment in windows
  • 原文地址:https://www.cnblogs.com/kelelipeng/p/14886076.html
Copyright © 2011-2022 走看看