I have used Code::Blocks IDE for DLL and Delphi 10.3 Rio for Delphi app.
Here are my C++ DLL codes (CPP File):
#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
}
Here is my .H File:
#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__
And here are my Delphi codes:
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.
According to this website PWideChar is Delphi equivalent of wchar_t* in C++: http://rvelthuis.de/articles/articles-dlls.html
So, when I clicked to Button1; I got this message:
And if DLL is not found, Delphi app throws this ('Application Stopped Working' Message):
So, SetErrorMode(0); is not working.
What I mean, I don't know anything about DLL programming and there is not any guideline about that in any website.
So, what should I do in order to make this working correctly?
On the C++ side, the conversion of wchar_t*
to std::string
is unnecessary. Just use the Unicode version of MessageBox()
instead, eg:
void DLL_EXPORT SomeFunction(wchar_t* sometext)
{
MessageBoxW(0, sometext, L"DLL Message", MB_OK | MB_ICONINFORMATION);
}
However, the main reason for your trouble is a calling convention mismatch. On the Delphi side, the default calling convention is register
, which is very different than the default of __cdecl
used in C and C++. The Delphi declaration of the DLL function needs to specify the correct calling convention, eg:
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;