工程源碼
https://download.csdn.net/download/csdn_z_s/1042776
開發環境
作業系統: win7 64位旗艦版
Java語言開發環境: Eclipse3.7(jdk1.6u45)
C/C++語言開發環境: cn_visual_studio_2010_ultimate_x86
VB語言開發環境: VB6.0
前言
我們的項目主要以java為編寫語言, 涉及到調用本地裝置的底層子產品使用的C/C++語言, java和C/C++之間利用JNI技術進行調用. 底層子產品在和本地裝置進行對接的方式之一是內建DLL(動态連結庫)的形式.
前段時間項目中需要內建第三方廠家(Y廠)的DLL(YC.DLL), Y廠的DLL是使用VB編寫的, 編譯環境是VB6.0. 拿到DLL後, 先用Dependency Walker看了下内部的接口名稱, 就四個:
DllCanUnloadNow
DllGetClassObject
DllRegisterServer
DllUnregisterServer
果然, 這就是傳說中的activeX, 從網上的資料看, VB6.0編譯出的dll均屬于activeX控件.
至于DLL, OCX, activeX, COM元件概念上的差別, 網上都有很好的資料.
小插曲
剛拿到Y廠的YC.DLL後, 按照下一節的步驟, 在編譯YC.DLL後, 編譯器會提示”無法加載的動态庫類型”, 而Y廠并沒有相關的C/C++技術支援可以提供C/C++對他們的DLL的調用方式. 雖然自己之前也寫過ocx控件, 将自己的ocx控件按照下一節的步驟, 編譯一切正常. 但自己沒有過在VB6.0編譯器上通過VB語言進行開發的經驗, 這讓開發進度一再停滞.
後來偶然間在網頁上查到一個在VS2010上引用VB6.0編譯的dll的文章, 截圖如下:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyN3YjNyADN2ETMyUDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
按照圖檔所說的步驟, 我的vs2010竟然真的可以引用Y廠的dll.
關于vb6controls.reg可以參考:
REGEDIT
HKEY_CLASSES_ROOT\Licenses = Licensing:Copying the keys may be a violation of established copyrights.
// Masked Edit Control 6.0 license key
HKEY_CLASSES_ROOT\Licenses\BC96F860-9928-11cf-8AFA-00AA00C00905= mmimfflflmqmlfffrlnmofhfkgrlmmfmqkqj
// Chart Control 6.0 (OLEDB) license key
HKEY_CLASSES_ROOT\Licenses\12B142A4-BD51-11d1-8C08-0000F8754DA1= aadhgafabafajhchnbchehfambfbbachmfmb
// Common Dialog Control 6.0 license key
HKEY_CLASSES_ROOT\Licenses\4D553650-6ABE-11cf-8ADB-00AA00C00905= gfjmrfkfifkmkfffrlmmgmhmnlulkmfmqkqj
// ADO Data Control 6.0 (OLEDB) license key
HKEY_CLASSES_ROOT\Licenses\C4145310-469C-11d1-B182-00A0C922E820= konhqhioohihphkouimonhqhvnwiqhhhnjti
// Common Controls-3 6.0 license key
HKEY_CLASSES_ROOT\Licenses\38911DA0-E448-11D0-84A3-00DD01104159= mcpckchcdchjcjcclidcgcgchdqdcjhcojpd
// Windows Common Controls-2 5.0 (SP2)license key
HKEY_CLASSES_ROOT\Licenses\9E799BF1-8817-11cf-958F-0020AFC28C3B= uqpqnqkjujkjjjjqwktjrjkjtkupsjnjtoun
// Windows Common Controls license key
HKEY_CLASSES_ROOT\Licenses\57CBF9E0-6AA7-11cf-8ADB-00AA00C00905= aahakhchghkhfhaamghhbhbhkbpgfhahlfle
// Data Bound Grid Control 5.0(SP3) licensekey
HKEY_CLASSES_ROOT\Licenses\556C75F1-EFBC-11CF-B9F3-00A0247033C4= xybiedobrqsprbijaegcbislrsiucfjdhisl
// Data Bound List Controls 6.0 license key
HKEY_CLASSES_ROOT\Licenses\096EFC40-6ABF-11cf-850C-08002B30345D= knsgigmnmngnmnigthmgpninrmumhgkgrlrk
// Internet Transfer Control 6.0 licensekey
HKEY_CLASSES_ROOT\Licenses\78E1BDD1-9941-11cf-9756-00AA00C00908= yjrjvqkjlqqjnqkjvprqsjnjvkuknjpjtoun
// Multimedia Control 6.0 license key
HKEY_CLASSES_ROOT\Licenses\B1EFCCF0-6AC1-11cf-8ADB-00AA00C00905= qqkjvqpqmqjjpqjjvpqqkqmqvkypoqjquoun
// Chart Control 6.0 license key
HKEY_CLASSES_ROOT\Licenses\7C35CA30-D112-11cf-8E72-00A0C90F26F8= whmhmhohmhiorhkouimhihihwiwinhlosmsl
// Windows Common Controls-2 6.0 licensekey
HKEY_CLASSES_ROOT\Licenses\4F86BADF-9F77-11d1-B1B7-0000F8753F5D= iplpwpnippopupiivjrioppisjsjlpiiokuj
// Windows Common Controls 6.0 license key
HKEY_CLASSES_ROOT\Licenses\ED4B87C4-9F76-11d1-8BF7-0000F8754DA1= knlggnmntgggrninthpgmnngrhqhnnjnslsh
// Comm Control 6.0 license key
HKEY_CLASSES_ROOT\Licenses\4250E830-6AC2-11cf-8ADB-00AA00C00905= kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun
// DataGrid Control 6.0 (OLEDB) license key
HKEY_CLASSES_ROOT\Licenses\CDE57A55-8B86-11D0-b3C6-00A0C90AEA82= ekpkhddkjkekpdjkqemkfkldoeoefkfdjfqe
// DataList Control 6.0 (OLEDB) license key
HKEY_CLASSES_ROOT\Licenses\A133F000-CCB0-11d0-A316-00AA00688B10= cibbcimbpihbbbbbnhdbeidiocmcbbdbgdoc
// DBWin license key
HKEY_CLASSES_ROOT\Licenses\D015B071-D2ED-11d0-A31A-00AA00688B10= gjdcfjpcmjicjcdcoihcechjlioiccechepd
// MSDBRPT license key
HKEY_CLASSES_ROOT\Licenses\9DF1A470-BA8E-11D0-849C-00A0C90DC8A9= cchcqjejhcgcqcfjpdfcdjkckiqikchcojpd
// FlexGrid Control 6.0 license key
HKEY_CLASSES_ROOT\Licenses\72E67120-5959-11cf-91F6-C2863C385E30= ibcbbbebqbdbciebmcobmbhifcmciibblgmf
// MAPI Controls 6.0 license key
HKEY_CLASSES_ROOT\Licenses\899B3E80-6AC6-11cf-8ADB-00AA00C00905= wjsjjjlqmjpjrjjjvpqqkqmqukypoqjquoun
// MSRDO 2.0 license key
HKEY_CLASSES_ROOT\Licenses\B1692F60-23B0-11D0-8E95-00A0C90F26F8= mjjjccncgjijrcfjpdfjfcejpdkdkcgjojpd
// RemoteData Control 6.0 license key
HKEY_CLASSES_ROOT\Licenses\43478d75-78e0-11cf-8e78-00a0d100038e= imshohohphlmnhimuinmphmmuiminhlmsmsl
// Windowless Controls 6.0 license key
HKEY_CLASSES_ROOT\Licenses\80E80EF0-DBBE-11D0-BCE2-00A0C90DCA10= qijimitpmpnpxplpvjnikpkpqoxjmpkpoivj
// PictureClip Control 6.0 license key
HKEY_CLASSES_ROOT\Licenses\6FB38640-6AC7-11cf-8ADB-00AA00C00905= gdjkokgdldikhdddpjkkekgknesjikdkoioh
// Rich TextBox Control 6.0 license key
HKEY_CLASSES_ROOT\Licenses\DC4D7920-6AC8-11cf-8ADB-00AA00C00905= iokouhloohrojhhhtnooiokomiwnmohosmsl
// Sheridan Tab Control license key
HKEY_CLASSES_ROOT\Licenses\190B7910-992A-11cf-8AFA-00AA00C00905= gclclcejjcmjdcccoikjlcecoioijjcjnhng
// SysInfo Control 6.0 license key
HKEY_CLASSES_ROOT\Licenses\E32E2733-1BC5-11d0-B8C3-00A0C90DCA10= kmhfimlflmmfpffmsgfmhmimngtghmoflhsg
// Winsock Control 6.0 license key
HKEY_CLASSES_ROOT\Licenses\2c49f800-c2dd-11cf-9ad6-0080c7e7b78d= mlrljgrlhltlngjlthrligklpkrhllglqlrk
內建方式-#import
文法:
#import "dllPath" no_namespace
使用#import語句, 然後對項目進行重新編譯, 編譯器會在工程目錄下生成兩個檔案:YC.tlh與YC.tli, 其中YC.tlh檔案類似于C/C++的頭檔案, 裡面有dll接口聲明:
struct__declspec(uuid("578277c2-7735-4c61-a141-1df16558cd4d"))
__SmartCardLib;
struct__declspec(uuid("fa7ab805-ec44-4a84-b876-52da8a5fe3c3"))
_clsSmartCard;
struct clsSmartCard;
struct__declspec(uuid("ff073a9e-e768-4024-b9cf-bcc05efd1329"))
__clsSmartCard;
_COM_SMARTPTR_TYPEDEF(_clsSmartCard,__uuidof(_clsSmartCard));
_COM_SMARTPTR_TYPEDEF(__clsSmartCard,__uuidof(__clsSmartCard));
struct__declspec(uuid("fa7ab805-ec44-4a84-b876-52da8a5fe3c3"))
_clsSmartCard : IDispatch
{
};
struct__declspec(uuid("5c4d3831-f09d-471b-82a0-0e84240c8afc"))
clsSmartCard;
struct__declspec(uuid("ff073a9e-e768-4024-b9cf-bcc05efd1329"))
__clsSmartCard : IDispatch
{
// Methods:
};
這個檔案告訴我們兩個非常重要的資訊:
一是, 通過” struct clsSmartCard;”這行代碼, 得知YC.DLL的
CLSID(5c4d3831-f09d-471b-82a0-0e84240c8afc ),CLSID可以認為是對接YC.DLL的入口.
二是, 通過_clsSmartCard : IDispatch 和__clsSmartCard :IDispatch 得知
_clsSmartCard 和 __clsSmartCard是DLL内部的接口聲明, 通過接口聲明, 我們可以知道這個動态庫為我們提供了哪些功能.
import.h
#import "C:\\YC.dll"no_namespace
智能指針
#include <Windows.h>
#include "import.h"
#include <atlbase.h>
void main_CComPtr(){
if(!SUCCEEDED(CoInitialize(NULL)))
{
return;
}
CLSID clsid;
HRESULT hr = CLSIDFromString(L"{5c4d3831-f09d-471b-82a0-0e84240c8afc}",&clsid);
if(!SUCCEEDED(hr))
{
return;
}
// 建立CLSID的另一種方式
//CLSIDclsid;
//clsid.Data1=0x5c4d3831;
//clsid.Data2=0xf09d;
//clsid.Data3=0x471b;
//clsid.Data4[0]=0x82;
//clsid.Data4[1]=0xa0;
//clsid.Data4[2]=0x0e;
//clsid.Data4[3]=0x84;
//clsid.Data4[4]=0x24;
//clsid.Data4[5]=0x0c;
//clsid.Data4[6]=0x8a;
//clsid.Data4[7]=0xfc;
CComPtr<_clsSmartCard> pGetRes;
pGetRes.CoCreateInstance(clsid);
printf("%d",pGetRes->Connect("gouqi"));
VARIANT cardNo;
VARIANT customNo;
VARIANT orderdate;
VARIANT orderAmount;
VARIANT orderNum;
VARIANT orderTotal;
VARIANT fgs;
VARIANT glz;
VARIANT cardStatus;
VARIANT factoryCode;
VARIANT cardPwd;
VARIANT cardType;
VARIANT chgPwd;
::VariantInit(&cardNo);
::VariantInit(&customNo);
::VariantInit(&orderdate);
::VariantInit(&orderAmount);
::VariantInit(&orderNum);
::VariantInit(&orderTotal);
::VariantInit(&fgs);
::VariantInit(&glz);
::VariantInit(&cardStatus);
::VariantInit(&factoryCode);
::VariantInit(&cardPwd);
::VariantInit(&cardType);
::VariantInit(&chgPwd);
pGetRes->readCard(&cardNo,
&customNo,
&orderdate,
&orderAmount,
&orderNum,
&orderTotal,
&fgs,
&glz,
&cardStatus,
&factoryCode,
&cardPwd,
&cardType,
&chgPwd );
pGetRes->Disconnect();
pGetRes.Release();
CoUninitialize();
}
CoGetClassObject
#include "import.h"
void mainCoGetClassObject(){
CoInitialize(NULL);
CLSID clsid;
HRESULT hr = CLSIDFromString(L"{5c4d3831-f09d-471b-82a0-0e84240c8afc}",&clsid);
if(!SUCCEEDED(hr))
{
return;
}
_clsSmartCard* ptr;
IClassFactory* p_classfactory;
hr=CoGetClassObject(clsid,CLSCTX_INPROC_SERVER,
NULL,IID_IClassFactory,
(LPVOID*)&p_classfactory);
p_classfactory->CreateInstance(NULL,__uuidof(_clsSmartCard),
(LPVOID*)&ptr);
printf("mainCoCreateInstance- > Connect=%d", ptr->Connect("gouqi"));
VARIANT cardNo;
VARIANT customNo;
VARIANT orderdate;
VARIANT orderAmount;
VARIANT orderNum;
VARIANT orderTotal;
VARIANT fgs;
VARIANT glz;
VARIANT cardStatus;
VARIANT factoryCode;
VARIANT cardPwd;
VARIANT cardType;
VARIANT chgPwd;
::VariantInit(&cardNo);
::VariantInit(&customNo);
::VariantInit(&orderdate);
::VariantInit(&orderAmount);
::VariantInit(&orderNum);
::VariantInit(&orderTotal);
::VariantInit(&fgs);
::VariantInit(&glz);
::VariantInit(&cardStatus);
::VariantInit(&factoryCode);
::VariantInit(&cardPwd);
::VariantInit(&cardType);
::VariantInit(&chgPwd);
ptr->readCard(&cardNo,
&customNo,
&orderdate,
&orderAmount,
&orderNum,
&orderTotal,
&fgs,
&glz,
&cardStatus,
&factoryCode,
&cardPwd,
&cardType,
&chgPwd );
ptr->Disconnect();
CoUninitialize();
}
C oCreateInstance
CoCreateInstance
#include "import.h"
void mainCoCreateInstance(){
CoInitialize(NULL);
CLSID clsid;
HRESULT hr = CLSIDFromString(L"{5c4d3831-f09d-471b-82a0-0e84240c8afc}",&clsid);
if(!SUCCEEDED(hr))
{
return;
}
_clsSmartCard *ptr;
hr=CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,
__uuidof(_clsSmartCard),(LPVOID*)&ptr);
printf("mainCoCreateInstance- > Connect=%d", ptr->Connect("gouqi"));
VARIANT cardNo;
VARIANT customNo;
VARIANT orderdate;
VARIANT orderAmount;
VARIANT orderNum;
VARIANT orderTotal;
VARIANT fgs;
VARIANT glz;
VARIANT cardStatus;
VARIANT factoryCode;
VARIANT cardPwd;
VARIANT cardType;
VARIANT chgPwd;
::VariantInit(&cardNo);
::VariantInit(&customNo);
::VariantInit(&orderdate);
::VariantInit(&orderAmount);
::VariantInit(&orderNum);
::VariantInit(&orderTotal);
::VariantInit(&fgs);
::VariantInit(&glz);
::VariantInit(&cardStatus);
::VariantInit(&factoryCode);
::VariantInit(&cardPwd);
::VariantInit(&cardType);
::VariantInit(&chgPwd);
ptr->readCard(&cardNo,
&customNo,
&orderdate,
&orderAmount,
&orderNum,
&orderTotal,
&fgs,
&glz,
&cardStatus,
&factoryCode,
&cardPwd,
&cardType,
&chgPwd );
ptr->Disconnect();
CoUninitialize();
}
LoadLibrary
#include <Windows.h>
#include "import.h"
#include "MainLoadLibrary.h"
extern "C"
{
typedefHRESULT (__stdcall *pFunc)(REFCLSIDrclsid,REFIID riid,LPVOID * ppv);
}
void main_LoadLibrary(){
if(!SUCCEEDED(CoInitialize(NULL)))
{
return;
}
HINSTANCE hdllInst = LoadLibrary("E:\\YC.dll");
pFunc func=(pFunc)GetProcAddress(hdllInst,"DllGetClassObject");
if (func !=NULL)
{
CLSID CLSID_SignCtrl_ocx;
HRESULT hr = CLSIDFromString(L"{5c4d3831-f09d-471b-82a0-0e84240c8afc}",&CLSID_SignCtrl_ocx);
if(!SUCCEEDED(hr))
{
return;
}
IClassFactory* pcf = NULL;
hr = func(CLSID_SignCtrl_ocx,IID_IClassFactory,(void**)&pcf);
if(SUCCEEDED(hr) && (pcf != NULL))
{
CLSID clsid;
clsid.Data1=0xfa7ab805;
clsid.Data2=0xec44;
clsid.Data3=0x4a84;
clsid.Data4[0]=0xb8;
clsid.Data4[1]=0x76;
clsid.Data4[2]=0x52;
clsid.Data4[3]=0xda;
clsid.Data4[4]=0x8a;
clsid.Data4[5]=0x5f;
clsid.Data4[6]=0xe3;
clsid.Data4[7]=0xc3;
_clsSmartCard* pCall = NULL;
hr = pcf->CreateInstance(NULL,clsid, (void**)&pCall);
if(SUCCEEDED(hr) && (pCall !=NULL))
{
printf("Connect=%d",pCall->Connect("gouqi"));
VARIANT cardNo;
VARIANT customNo;
VARIANT orderdate;
VARIANT orderAmount;
VARIANT orderNum;
VARIANT orderTotal;
VARIANT fgs;
VARIANT glz;
VARIANT cardStatus;
VARIANT factoryCode;
VARIANT cardPwd;
VARIANT cardType;
VARIANT chgPwd;
::VariantInit(&cardNo);
::VariantInit(&customNo);
::VariantInit(&orderdate);
::VariantInit(&orderAmount);
::VariantInit(&orderNum);
::VariantInit(&orderTotal);
::VariantInit(&fgs);
::VariantInit(&glz);
::VariantInit(&cardStatus);
::VariantInit(&factoryCode);
::VariantInit(&cardPwd);
::VariantInit(&cardType);
::VariantInit(&chgPwd);
pCall->readCard(&cardNo,
&customNo,
&orderdate,
&orderAmount,
&orderNum,
&orderTotal,
&fgs,
&glz,
&cardStatus,
&factoryCode,
&cardPwd,
&cardType,
&chgPwd );
pCall->Disconnect();
}
pcf->Release();
} else{
printf("false");
}
}
FreeLibrary(hdllInst);
CoUninitialize();
getchar();
}