关于动态链接库的具体介绍参考本人转载博客:进程间通信详解 - 动态链接库实现
下文说说自己编写的动态链接库,主要作用是实现用VC++编写的A程序和用C++builder编写的B程序之间的通信,其中涉及结构体,所以需要注意一下,
1>动态链接库myDLL
新建一个dll工程(MFC AppWizard(dll)),并命名myDLL,这个工程中有三种形式:
1.动态链接库和MFC静态链接
2.动态链接库使用共享MFC DLL
3.MFC扩展DLL(使用共享 MFC DLL)
这三者的区别解释如下:静态dll中编译时嵌入了mfc的类文件,所以客户机上即使没有mfc的库文件也能运行你的dll,动态的dll运行时会调用系统的mfc库,所以客户机要想运行你的dll必须系统中必须有mfc库文件。常规mfc dll(前两种)不能导出类,只能导出函数,扩展的mfc dll则可以导出类。
我在此选用了第二种,建完工程后,在myDLL.h中添加内容
// myDLL.h : main header file for the MYDLL DLL
//
#if !defined(AFX_MYDLL_H__C094CB0F_D564_446A_BEB7_FA2E437933BB__INCLUDED_)
#define AFX_MYDLL_H__C094CB0F_D564_446A_BEB7_FA2E437933BB__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h" // main symbols
/
// CMyDLLApp
// See myDLL.cpp for the implementation of this class
//
//添加内容
#ifdef DLL_API
#else
#define DLL_API extern "C" _declspec(dllexport) 注意1
#endif
typedef struct GongJianT
{
double h_X;
double h_Y;
double w_Z;
double w_XX;
double w_YY;
double w_ZZ;
}m_GongJianT;
DLL_API void SetData(double tmpData);
DLL_API double GetData();
DLL_API void SetSign(int msign);
DLL_API int GetSign();
DLL_API void SetGJTData(m_GongJianT *m_GJT);
DLL_API void GetGJTData(m_GongJianT *m_GJT);
class CMyDLLApp : public CWinApp
{
public:
CMyDLLApp();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMyDLLApp)
//}}AFX_VIRTUAL
//{{AFX_MSG(CMyDLLApp)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MYDLL_H__C094CB0F_D564_446A_BEB7_FA2E437933BB__INCLUDED_)
在myDLL.cpp添加内容:
// myDLL.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include "myDLL.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma data_seg("SharedDataInDll")
//初始化为 0
double data =0.0;
int Sign=0;
m_GongJianT m_GJT1={0.0,0.0,0.0,0.0,0.0,0.0};注意2,结构体必须初始化。
#pragma data_seg()
#pragma comment(linker, "/SECTION:SharedDataInDll,RWS")
//设置工件台数据
void SetGJTData(m_GongJianT *m_GJT)
{
m_GJT1.h_X =m_GJT->h_X ;
m_GJT1.h_Y =m_GJT->h_Y ;
m_GJT1.w_Z =m_GJT->w_Z ;
m_GJT1.w_XX=m_GJT->w_XX;
m_GJT1.w_YY=m_GJT->w_YY;
m_GJT1.w_ZZ=m_GJT->w_ZZ;
}
//返回工件台数据
void GetGJTData(m_GongJianT *m_GJT)
{
m_GJT->h_X =m_GJT1.h_X ;
m_GJT->h_Y =m_GJT1.h_Y ;
m_GJT->w_Z =m_GJT1.w_Z ;
m_GJT->w_XX=m_GJT1.w_XX;
m_GJT->w_YY=m_GJT1.w_YY;
m_GJT->w_ZZ=m_GJT1.w_ZZ;
}
//返回共享数据
double GetData()
{ return data;}
//设置共享数据
void SetData(double tmpData)
{data = tmpData;}
void SetSign(int msign)
{
Sign=msign;
}
int GetSign()
{
return Sign;
}
//
// Note!
//
// If this DLL is dynamically linked against the MFC
// DLLs, any functions exported from this DLL which
// call into MFC must have the AFX_MANAGE_STATE macro
// added at the very beginning of the function.
//
// For example:
//
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
// {
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
// // normal function body here
// }
//
// It is very important that this macro appear in each
// function, prior to any calls into MFC. This means that
// it must appear as the first statement within the
// function, even before any object variable declarations
// as their constructors may generate calls into the MFC
// DLL.
//
// Please see MFC Technical Notes 33 and 58 for additional
// details.
//
/
// CMyDLLApp
BEGIN_MESSAGE_MAP(CMyDLLApp, CWinApp)
//{{AFX_MSG_MAP(CMyDLLApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/
// CMyDLLApp construction
CMyDLLApp::CMyDLLApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/
// The one and only CMyDLLApp object
CMyDLLApp theApp;
编译后便可生成myDLL.dll和myDLL.lib文件。
以后的过程就开始用A程序和B程序进行调用,
1、用extern "C"修饰VC导出的DLL函数。如:extern "C" __declspec(dllimport) int aFunc(int a);
2、用C++Builder的implib工具生成DLL对应的lib文件。如:implib xx.lib xxx.dll。生成lib文件之后,C++Builder便可以使用这个lib文件了。
2> VC++编写的A程序需要添加的文件:
ShareDll.h
#ifndef SHARED_DLL
#define SHARED_DLL
//在 DLL 项目中设置 DLL_API 为导出类型 extern "C" _declspec(dllimport)
//在 Test 项目中则无需设置该 DLL_API , 直接使用这个 CalculateDLL.h 文件即可
#ifdef DLL_API
#else
#define DLL_API extern "C" _declspec(dllimport)
#endif
typedef struct GongJianT
{
double h_X;
double h_Y;
double w_Z;
double w_XX;
double w_YY;
double w_ZZ;
}m_GongJianT;
DLL_API void SetData(int tmpData);
DLL_API int GetData();
DLL_API void SetGJTData(m_GongJianT *m_GJT);
DLL_API void GetGJTData(m_GongJianT *m_GJT);
#endif
在需要调用动态链接库的源文件中需要添加:
#include "ShareDLL.h"
#pragma comment(lib, "myDLL.lib")
3> C++builder编写的B程序中需添加:
ShareDll.h
#ifndef SHARED_DLL
#define SHARED_DLL
//在 DLL 项目中设置 DLL_API 为导出类型 extern "C" _declspec(dllimport)
//在 Test 项目中则无需设置该 DLL_API , 直接使用这个 CalculateDLL.h 文件即可
#ifdef DLL_API
#else
#define DLL_API extern "C" _declspec(dllimport)
#endif
typedef struct GongJianT
{
double h_X;
double h_Y;
double w_Z;
double w_XX;
double w_YY;
double w_ZZ;
}m_GongJianT;
DLL_API _stdcall void SetData(int tmpData);
DLL_API _stdcall int GetData();
DLL_API _stdcall void SetGJTData( m_GongJianT *m_GJT);
DLL_API _stdcall void GetGJTData( m_GongJianT *m_GJT);注意3,和A程序中的不同
#endif
在使用动态链接库中函数的源文件中需添加
#include "ShareDLL.h"
#pragma comment(lib, "bcb.lib") //bcb.lib是通过implib bcb.lib myDLL.dll命令生成的,
注意:myDLL.dll myDLL.lib bcb.lib 需要包含在用到它的程序中