您的位置:首页 > 编程语言 > C#

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

2017-07-19 22:48 218 查看
今天在项目中看到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));
}
/// <summary>
/// 函数指针
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
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 <iostream>
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: