我有一个问题,我已经整整一个星期了,而且我自己也无法解决这个问题。我一直在googeling,并在各种论坛上搜索......我发现很多“这可能有效”,尝试过,但没有,没有成功。如果有人有任何线索,请,请帮助我!
我从外部源获得了很多用VB编写的类和函数,我需要能够在C ++应用程序中使用它们。我的第一个问题是:没问题,我将VB代码转换为dll,并从我的C ++程序中加载它。这虽然比我想象的要难。我的C ++程序不是用Visual Studio编写的,但为了简单起见,我开始尝试从Visual Studio C ++应用程序加载我的VB dll(用Visual Studio 2010编写)。到目前为止,这是我的代码:
VB代码:DllModule:类库项目
DllModule.vb
Namespace DllModule
Public Module DllModule
Public Const DLL_PROCESS_DETACH = 0
Public Const DLL_PROCESS_ATTACH = 1
Public Const DLL_THREAD_ATTACH = 2
Public Const DLL_THREAD_DETACH = 3
Public Function DllMain(ByVal hInst As Long, ByVal fdwReason As Long,
ByVal lpvReserved As Long) As Boolean
Select Case fdwReason
Case DLL_PROCESS_DETACH
' No per-process cleanup needed
Case DLL_PROCESS_ATTACH
DllMain = True
Case DLL_THREAD_ATTACH
' No per-thread initialization needed
Case DLL_THREAD_DETACH
' No per-thread cleanup needed
End Select
Return True
End Function
'Simple function
Public Function Add(ByVal first As Integer, ByVal sec As Integer) As Integer
Dim abc As Integer
abc = first + sec
Return abc
End Function
End Module
End Namespace
DllModule.def
NAME DllModule
LIBRARY DllModule
DESCRIPTION "My dll"
EXPORTS DllMain @1
Add @2
C ++ - 代码:TryVbDllLoad:控制台应用程序
TryVbDllLoad.cpp
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <strsafe.h>
extern "C" {
__declspec(dllimport) int __stdcall Add(int, int);
}
typedef int (__stdcall *ptf_test_func_1_type)(int, int);
int __cdecl _tmain(int argc, _TCHAR* argv[])
{
HINSTANCE hdll = NULL;
hdll = LoadLibrary("DllModule.dll"); // load the dll
if(hdll) {
ptf_test_func_1_type p_func1=(ptf_test_func_1_type)GetProcAddress(hdll,"Add");
if(p_func1) {
int ret_val = (*p_func1)(1, 2);
} else {
DWORD dw = GetLastError();
}
FreeLibrary(hdll); // free the dll
} else {
DWORD dw = GetLastError();
}
return 0;
}
我可以加载dll,但是GetProcAddess返回NULL,错误代码为127(无法找到指定的过程)。
我试过从VB应用程序加载dll。这有效(即使没有.def文件)。但我猜测没有创建C ++应用程序可以使用的正确入口点(当我在Dependency Walker中打开dll时,我看不到入口点或函数)。我已经尝试使用和不使用“Register for COM interop”编译VB代码。
1)我做错了什么?
2)如果没有任何好方法可以正确解决这个问题,我该怎么做而不是创建一个dll?有没有其他方法可以在我的C ++应用程序中使用VB类和函数?
亲切的问候
萨拉
感谢您的回答母马!
我的dll中肯定会出现某种错误,因为当我尝试注册时使用的是regsvr32我得到:“模块C:/tmp/DllModule.dll已加载,但未找到DllRegisterServer的起始地址检查C:/tmp/DllModule.dll是否是有效的DLL或OCX文件,然后重试。“
另外,当我使用
时 #import "C\tmp\DllModule.dll"
我得到了
fatal error C1083: Cannot open type library file: 'c:\tmp\dllmodule.dll'
我查看了教程的链接,但是有一个小问题:在所有项目类型中没有“ActiveX DLL”这样的东西可供选择。是的,我确实有Visual Studio 2010 Professional(试用版,但仍然)。
- Sara
答案 0 :(得分:4)
感谢所有输入。我遇到了另一种解决问题的方法,使用多文件程序集而不是我的第一个dll方法。
我遵循了这个HowTo节:http://msdn.microsoft.com/en-us/library/226t7yxe.aspx#Y749
VB代码:DllModule:类库项目
DllModule.vb
Imports System.Runtime.InteropServices
Namespace DllModuleNS
Public Class Class1
Public Function ClassAdd(ByRef first As Integer, ByRef sec As Integer) As Integer
Dim abc As Integer
abc = first + sec
Return abc
End Function
End Class
End Namespace
这个文件我使用visual studio(生成DllModule.dll文件)和cmd-line编译:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Vbc.exe /t:module DllModule.vb
(生成DllModule.netmodule文件)。
C ++ - 代码:TryVbDllLoad:控制台应用程序
TryVbDllLoad.cpp
#using <mscorlib.dll>
#using ".\..\ClassLibrary1\DllModule.netmodule"
using namespace DllModule::DllModuleNS;
int _tmain(int argc, _TCHAR* argv[])
{
Class1^ me = gcnew Class1();
int a = 1, b = 2;
int xx = me->ClassAdd(a, b);
return 0;
}
在TryVBDllLoad-project属性中,我改变了:
这导致我可以在VC ++代码中使用VB类Class1!
我现在更进了一步,并将TryVBDllLoad项目更改为dll:
TryVbDllLoadClass.h
#ifndef TryVbDllLoadClass_H
#define TryVbDllLoadClass_H
class TryVbDllLoadClass
{
public:
TryVbDllLoadClass();
int Add(int a, int b);
};
#endif // TryVbDllLoadClass_H
TryVbDllLoadClass.cpp
#include "TryVbDllLoadClass.h"
#using <mscorlib.dll>
#using ".\..\ClassLibrary1\DllModule.netmodule"
using namespace DllModule::DllModuleNS;
TryVbDllLoadClass::TryVbDllLoadClass() {}
int TryVbDllLoadClass::Add(int a, int b)
{
Class1^ me = gcnew Class1();
int xx = me->ClassAdd(a, b);
return xx;
}
DllExport.h
#ifndef DLLEXPORT_H
#define DLLEXPORT_H
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#ifdef __dll__
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif // __dll__
extern "C" {
IMPEXP int __stdcall AddFunction(int);
}
#endif // DLLEXPORT_H
DllMain.h
#define __dll__
#include "dllExport.h"
#include " TryVbDllLoadClass.h"
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
return 1;
}
TryVbDllLoadClass * my;
IMPEXP int __stdcall AddFunction(int first, int second)
{
my = new TryVbDllLoadClass();
int res = my->Add(first, second);
delete my;
return res;
}
这个dll我可以像普通的dll一样添加到非visual-studio项目中:
C ++ - 代码:LoadDll:非Visual-Studio项目(本例中为CodeBlocks)
的main.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "dllExport.h"
typedef int( * LPFNDLL_CREATE)(int, int);
HINSTANCE hDLL;
LPFNDLL_CREATE func;
using namespace std;
int main()
{
cout << "Hello world!" << endl;
int key = 35;
hDLL = LoadLibrary("TryVbDllLoadClass.dll");
if(hDLL)
{
cout << "Loaded: " << hDLL << endl;
func = (LPFNDLL_CREATE) (GetProcAddress(hDLL, "_AddFunction@4"));
if(func != NULL)
{
cout << "Connected: " << func << endl;
cout << "Function returns: " << func(key, key) << endl;
}
else cout << " ::: fail: " << GetLastError() << endl;
FreeLibrary(hDLL);
cout << "Freed" << endl;
}
else cout << " ::: fail: " << GetLastError() << endl;
printf("-> Goodbye world!\n");
return 0;
}
答案 1 :(得分:1)
使用VB你不会得到一个“正常”的DLL(至少在以前的情况下是这样)。 并且您没有获得功能的入口点。
但是据我了解你,你有VB源代码,你可以用它做任何事情 有必要的。这是一个可能的解决方案:
http://www.codeproject.com/Articles/21/Beginner-s-Tutorial-Calling-Visual-Basic-ActiveX-D
但首先尝试这种不太复杂的方式, 因为我认为VB dll总是一个COM dll,所以你可以:
使用Windows命令注册dll
regsvr32 F:\proj\VBDllModule.dll
现在是您的C ++代码:
#import "F:\proj\VBDllModule.dll"
using namespace DllModule;
void CDialogTestDlg::OnButton1()
{
HRESULT hresult;
CLSID clsid;
_CTest *t; // a pointer to the CTest object
_bstr_t bstrA = L"hello";
_bstr_t bstrB = L" world";
_bstr_t bstrR;
::CoInitialize(NULL);
hresult=CLSIDFromProgID(OLESTR("VBTestLib.CTest"), &clsid);
hresult= CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,
__uuidof(_CTest),(LPVOID*) &t);
if(hresult == S_OK)
{
bstrR = t->vbConcat(bstrA , bstrB);
AfxMessageBox((char*)bstrR);
}
}