从 Delphi 应用程序调用时,如何修复 C++ DLL 中 MessageBox 中显示的无效字符?
How to fix invalid characters which shown in MessageBox in C++ DLL when calling it from Delphi app?
我为 DLL 使用了 Code::Blocks IDE,为 Delphi 应用程序使用了 Delphi 10.3 Rio。
这是我的 C++ DLL 代码(CPP 文件):
#include "main.h"
#include "string"
#include "wchar2string.h"
using namespace std;
// a sample exported function
void DLL_EXPORT SomeFunction(wchar_t* sometext)
{
string str = wchar2string(sometext);
const char* cch = str.c_str();
MessageBox(0, cch, "DLL Message", MB_OK | MB_ICONINFORMATION);
}
extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// attach to process
// return FALSE to fail DLL load
break;
case DLL_PROCESS_DETACH:
// detach from process
break;
case DLL_THREAD_ATTACH:
// attach to thread
break;
case DLL_THREAD_DETACH:
// detach from thread
break;
}
return TRUE; // succesful
}
这是我的 .H 文件:
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
/* To use this exported function of dll, include this header
* in your project.
*/
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
void DLL_EXPORT SomeFunction(wchar_t* sometext);
#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__
这是我的 Delphi 代码:
const
DLL = 'deneme dll.dll';
procedure MyProcedure(sometext: PWideChar); external DLL name 'SomeFunction';
procedure TForm1.Button1Click(Sender: TObject);
var
MyString: String;
begin
MyString := Edit1.Text;
MyProcedure(PWideChar(MyString));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
SetErrorMode(0);
end;
end.
根据该网站 PWideChar Delphi 等同于 C++ 中的 wchar_t*:http://rvelthuis.de/articles/articles-dlls.html
因此,当我单击 Button1 时;我收到这条消息:
如果未找到 DLL,Delphi 应用会抛出此消息('Application Stopped Working' 消息):
因此,SetErrorMode(0); 不工作。
我的意思是,我对 DLL 编程一无所知,而且在任何网站上都没有任何相关指南。
那么,我应该怎么做才能使其正常工作?
在 C++ 方面,wchar_t*
到 std::string
的转换是不必要的。只需使用 MessageBox()
的 Unicode 版本,例如:
void DLL_EXPORT SomeFunction(wchar_t* sometext)
{
MessageBoxW(0, sometext, L"DLL Message", MB_OK | MB_ICONINFORMATION);
}
但是,您遇到麻烦的主要原因是调用约定不匹配。在 Delphi 方面,默认调用约定是 register
,这与 C 和 C++ 中使用的默认 __cdecl
非常 不同。 DLL函数的Delphi声明需要指定正确的调用约定,例如:
procedure MyProcedure(sometext: PWideChar); cdecl; external DLL name 'SomeFunction';
procedure TForm1.Button1Click(Sender: TObject);
var
MyString: UnicodeString;
begin
MyString := Edit1.Text;
MyProcedure(PWideChar(MyString));
end;
我为 DLL 使用了 Code::Blocks IDE,为 Delphi 应用程序使用了 Delphi 10.3 Rio。
这是我的 C++ DLL 代码(CPP 文件):
#include "main.h"
#include "string"
#include "wchar2string.h"
using namespace std;
// a sample exported function
void DLL_EXPORT SomeFunction(wchar_t* sometext)
{
string str = wchar2string(sometext);
const char* cch = str.c_str();
MessageBox(0, cch, "DLL Message", MB_OK | MB_ICONINFORMATION);
}
extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// attach to process
// return FALSE to fail DLL load
break;
case DLL_PROCESS_DETACH:
// detach from process
break;
case DLL_THREAD_ATTACH:
// attach to thread
break;
case DLL_THREAD_DETACH:
// detach from thread
break;
}
return TRUE; // succesful
}
这是我的 .H 文件:
#ifndef __MAIN_H__
#define __MAIN_H__
#include <windows.h>
/* To use this exported function of dll, include this header
* in your project.
*/
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"
{
#endif
void DLL_EXPORT SomeFunction(wchar_t* sometext);
#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__
这是我的 Delphi 代码:
const
DLL = 'deneme dll.dll';
procedure MyProcedure(sometext: PWideChar); external DLL name 'SomeFunction';
procedure TForm1.Button1Click(Sender: TObject);
var
MyString: String;
begin
MyString := Edit1.Text;
MyProcedure(PWideChar(MyString));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
SetErrorMode(0);
end;
end.
根据该网站 PWideChar Delphi 等同于 C++ 中的 wchar_t*:http://rvelthuis.de/articles/articles-dlls.html
因此,当我单击 Button1 时;我收到这条消息:
如果未找到 DLL,Delphi 应用会抛出此消息('Application Stopped Working' 消息):
因此,SetErrorMode(0); 不工作。
我的意思是,我对 DLL 编程一无所知,而且在任何网站上都没有任何相关指南。
那么,我应该怎么做才能使其正常工作?
在 C++ 方面,wchar_t*
到 std::string
的转换是不必要的。只需使用 MessageBox()
的 Unicode 版本,例如:
void DLL_EXPORT SomeFunction(wchar_t* sometext)
{
MessageBoxW(0, sometext, L"DLL Message", MB_OK | MB_ICONINFORMATION);
}
但是,您遇到麻烦的主要原因是调用约定不匹配。在 Delphi 方面,默认调用约定是 register
,这与 C 和 C++ 中使用的默认 __cdecl
非常 不同。 DLL函数的Delphi声明需要指定正确的调用约定,例如:
procedure MyProcedure(sometext: PWideChar); cdecl; external DLL name 'SomeFunction';
procedure TForm1.Button1Click(Sender: TObject);
var
MyString: UnicodeString;
begin
MyString := Edit1.Text;
MyProcedure(PWideChar(MyString));
end;