C#与C++代码互相调用

今天在项目中看到C:\WINDOWS\Microsoft.NET\Framework\v...\REGASM.exe /regfile:xxx.reg xxx.dll,注册COM组件。

开始不明白为啥要注册COM组件,c#自己调自己的dll用不着这样啊,网上查看大都是讲如何注册COM组件。

经过不懈网上游荡,原来注册COM组件是给其他语言调用的,因为c#程序是托管代码,所以和其他非托管代码有所差异。

查就查到底,继续在网上查资料,把这块东西系统的整理下:

1.c#引用托管程序集-----直接引用

2.c#引用非托管代码-----通过P/Invoke(Plateform Invoke)机制调用dll函数

IntPtr相当于指针,通过Marshal类操作非托管内存

C代码和C++代码编译方式不同,C语言编译出来的函数入口和函数名一样,但C++编译出来的入口和函数名不一样,这是因为有重载的关系;这时,如果是C++代码,要么在函数名前加extern "C" rvalue function(param...),要么在编译出来的dll用dumpbin类似工具反编译出来函数入口EntryPoint

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        动态调用

    public static class NativeMethod     
    {     
        [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]     
        public static extern int LoadLibrary(     
            [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);     
    
        [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]     
        public static extern IntPtr GetProcAddress(int hModule,     
            [MarshalAs(UnmanagedType.LPStr)] string lpProcName);     
    
        [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]     
        public static extern bool FreeLibrary(int hModule);     
    }
        static void Main(string[] args)     
        { 
             //1.load c++ dll
             int hModule = NativeMethod.LoadLibrary(@"c:/CppDemo.dll");
             if (hModule == 0)
                 return;
             IntPtr intPtr = NativeMethod.GetProcAddress(hModule, "MyDelegate");
             MyDelegate myDele = (MyDelegate)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(MyDelegate));
             Console.WriteLine(myDele(1,2));
         }
        ///      
        /// 函数指针     
        ///      
        ///      
        ///      
        ///      
        delegate int MyDelegate(int a, int b);     

3. clr c++调用c#dll

   设置项目属性-->配置属性-->常规-->公共语言运行时支持-->公共语言运行时支持(clr)

#using "../debug/xx.dll"
using namespace xxx;
然后按照托管c++/clr的语法:托管对象使用^……

4.非托管c++调用c#dll

1)用c#写dll

写接口和实现类,贴上GUID特性标签(工具->创建GUID->选择5->复制),Properties下的AssemblyInfo.cs中ComVisible为true

2)注册dll为COM组件

如果在本机开发,在属性->生成->为COM互操作注册即能完成注册功能或应用程序->程序集信息

但是要在别的机子上使用那就需要用REGASM.exe来注册

                C:\WINDOWS\Microsoft.NET\Framework\v...\REGASM.exe /regfile:xxx.reg xxx.dll然后运行xxx.reg注册该COM组件

3)使用 

namespace ComInteropDemo     
{     
    //接口声明     
    [Guid("7103C10A-2072-49fc-AD61-475BEE1C5FBB")]       
    public interface ComInteropInterface     
    {     
        [DispId(1)]     
        int Add(int a, int b);     
    
        [DispId(2)]     
        int Minus(int a, int b);     
    }     
       
    //对于实现类的声明     
    [Guid("87796E96-EC28-4570-90C3-A395F4F4A7D6")]     
    [ClassInterface(ClassInterfaceType.None)]     
    public class ComInterop : ServicedComponent, ComInteropInterface     
    {     
        public ComInterop() { }     
    
        public int Add(int a, int b)     
        {     
            return a + b;     
        }     
    
        public int Minus(int a, int b)     
        {     
            return a - b;     
        }     
    }     
}
#include "stdafx.h"     
#include      
using namespace std;     
        
#import "..//Debug//ComInteropDemo.tlb"     
//路径一定要正确         
int _tmain(int argc, _TCHAR* argv[])     
{     
    HRESULT hr;         
    //ComInteropDemo::ComInterop *p;     
         
    CoInitialize ( NULL );        
    
    //创建智能指针ComInteropDemo::ComInteropInterface     
    ComInteropDemo::ComInteropInterfacePtr ptr;        
    //创建实例     
    hr = ptr.CreateInstance(__uuidof (ComInteropDemo::ComInterop));         
    if(hr == S_OK)     
    {     
        cout << ptr->Add (1.0, 2.0);     
    }            
    
    CoUninitialize ();     
    return 0;     
}

你可能感兴趣的:(C#,C++)