C++利用C#的Com的接口制作dll

C++deDLL的制作

1、首先是头文件

#pragma once
#ifndef _ANIMAL_H
#define _ANIMAL_H

#ifdef __cplusplus
extern "C"
{
#endif

#ifdef DLLCLASS_EXPORTS
#define CREATEANIMALDLL_API_DU _declspec(dllexport)
#else                                                                            
#define CREATEANIMALDLL_API_DU _declspec(dllimport) //当编译时,头文件不参加编译,所以.cpp文件中先定义,后头文件被包含进来,因此外部使用时,为dllexport,而在内部编译时,则为dllimport
#endif   

class CREATEANIMALDLL_API_DU animal              //需要被外界调用的类(父类)
{
public:
    virtual int outDate() = 0;                 //纯虚函数
    void getWide(int x) ;
    void getHigh(int y) ;

protected:
    int wide;
    int high;
};


class CREATEANIMALDLL_API_DU cat :public animal      //需要被调用的类(子类cat)
{
public:
    int outDate();
};

class  CREATEANIMALDLL_API_DU dog :public animal     //需要被调用的类(子类dog)
{
public:
    int outDate();
    void getWide(int x);
    void getHigh(int y);
};

int CREATEANIMALDLL_API_DU exportDate();             //需要被调用的函数(单独的一个函数,不属于任何一个类)

int CREATEANIMALDLL_API_DU add(int a, int b);

int CREATEANIMALDLL_API_DU ptr_dog(dog** Dog);

int CREATEANIMALDLL_API_DU Mes_add(int a, int b);

#ifdef __cplusplus
}
#endif

#endif

extern "C"是必须要加的否则编译出来的dll库,使用动态调用时是识别不到函数的,原因是C++和C语言在生成dll库时的函数名是不一定相同的

2、源文件(函数接口的实现以及如何调用C#Com口的接口)

#include "pch.h"
#include <iostream>
#define DLLCLASS_EXPORTS
#include "animal.h"

using namespace std;
//父类中函数实现 
void CREATEANIMALDLL_API_DU animal::getWide(int x) {
    wide = x;
}
void CREATEANIMALDLL_API_DU animal::getHigh(int y) {
    high = y;
}//子类cat中数据输出实现

int CREATEANIMALDLL_API_DU cat::outDate() {
    return (wide + high); 
}//子类dog数据输出实现

int CREATEANIMALDLL_API_DU dog::outDate() {
    return (wide - high);
}//函数的实现
void CREATEANIMALDLL_API_DU dog::getWide(int x) {
    wide = x;
}
void CREATEANIMALDLL_API_DU dog::getHigh(int y) {
    high = y;
}//子类cat中数据输出实现
int CREATEANIMALDLL_API_DU exportDate() {
    return 666;
}
int CREATEANIMALDLL_API_DU add(int a,int b)
{
    return a + b;
}

int CREATEANIMALDLL_API_DU ptr_dog(dog** Dog)
{
    *Dog = new dog();
    return 0;
}

extern int Add(int a, int b);
int CREATEANIMALDLL_API_DU Mes_add(int a, int b)
{
    return Add(a, b);
}

在动态生成调用DLL时,注意指针接口只能只想从父类继承并实现的虚函数,以及自己的新增的函数,无法指向父类函数,否则编译时会出问题。

#include "pch.h"
#include <iostream>
//#include <atlstr.h>
#import "../Mes/Mes.tlb"

class MesInterface
{
public:
	MesInterface()
	{
		CoInitialize(NULL);
		mHr = mPtr.CreateInstance(__uuidof (Mes::EiotMes));
		if (mHr != S_OK)
		{
			//::AfxMessageBox("请注册组件!", 0);
			MessageBoxA(NULL,"请注册组件!", 0, MB_OK);
		}
	}
	~MesInterface()
	{
		CoUninitialize();
	}	

	int Add(int x, int y)
	{
		if (mHr == S_OK)
		{
			return mPtr->Add(x, y);
		}
		return -1;
	}

private:
	HRESULT mHr;
	Mes::IMesInterfacePtr mPtr;
};


int Add(int a, int b)
{
	MesInterface mes;
	return mes.Add(a, b);
}

//#using "../Mes/Mes.dll"

环境配置

一般包含一下C#生成com口tlb文件的接口就行

 

如何调用

静态调用时包含头文件以及环境配置如下

头文件同上

环境配置如下

 

动态调用时不需要配置文件

调用的.c 文件

#include <iostream>
#include "animal.h"
#include<windows.h>
using namespace std;

#pragma comment(lib, "MakeDll_Cplus.lib")
int main()
{
    //dll的
    {
        cout << exportDate() << endl;          //调用函数输出666   

        dog DOG;     //实例化dog对象、赋值、并输出。
        DOG.getHigh(5);
        DOG.getWide(6);
        cout << DOG.outDate() << endl;

        cat CAT;    //实例化cat对象、赋值、并输出
        CAT.getHigh(16);
        CAT.getWide(4);
        cout << CAT.outDate() << endl;
    std::cout << Mes_add(1, 10) << std::endl;
    }

    HMODULE module = LoadLibraryA("MakeDll_Cplus.dll");     // 根据DLL文件名,加载DLL,返回一个模块句柄
    if (module == NULL)
    {
        printf("加载DLLTest1.dll动态库失败\n");
        return 0;
    }

    typedef  int(*Mes_add)(int,int);
    Mes_add Mes_Add;
    Mes_Add = (Mes_add)GetProcAddress(module, "add");

    std::cout << Mes_Add(1, 10) << std::endl;

    typedef  int(*AddFunc)(int,int);
    AddFunc add1;
    add1 = (AddFunc)GetProcAddress(module, "add");
    if (add1 == NULL)
    {
        std::cout << "GetProcAddress(module, \"add\") fail\n" << endl;
        return 0;
    }
    std::cout << add1(1,2) << endl;


    typedef  int(*ExportDate)();
    ExportDate ExportDate1;
    ExportDate1 = (ExportDate)GetProcAddress(module, "exportDate");
    if (ExportDate1 == NULL)
    {
        std::cout << "GetProcAddress(module, \"exportDate\") fail\n" << endl;
        return 0;
    }
    std::cout << ExportDate1() << endl;

    typedef int (*Ptr_dog)(dog** ptr_dog);
    Ptr_dog ptr_dog;
    dog* Dog = NULL;
    ptr_dog = (Ptr_dog)GetProcAddress(module, "ptr_dog");
    if (ptr_dog == NULL)
    {
        std::cout << "GetProcAddress(module, \"ptr_dog\") fail\n";
        return 0;
    }

    ptr_dog(&Dog);

    cout<< Dog->outDate()<<endl;

    if (module != NULL)
    {
        FreeLibrary(module);
        module = NULL;
    }

    std::cout << "Hello World!\n";
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值