I have a mission to call Matlab functions from C++ poject. I know there are several ways to do that, I prefer to use it through Matlab Engine.
I have several m-files work perfect in Matlab enviroment.
mymat.m
function myfig()
figure;
end
I made a dll-wrapper in C++ to connect the m-files with C++.
dllwrap.h
#pragma once
#include <Engine.h>
#pragma comment ( lib,"libmx.lib" )
#pragma comment ( lib,"libmat.lib" )
#pragma comment ( lib,"libeng.lib" )
#pragma comment ( lib,"libmex.lib" )
#ifdef DLLWRAP_EXPORTS
#define DLLWRAP_API __declspec(dllexport)
#else
#define DLLWRAP_API __declspec(dllimport)
#endif
DLLWRAP_API bool TestDll();
DLLWRAP_API void MyFigure();
dllwrap.cpp
#include "stdafx.h"
#include "dllwrap.h"
Engine* pEng = NULL;
void StartVirtualEngineMatlab()
{
if ((pEng = engOpen(NULL)) == NULL)
{
MessageBoxA(NULL, (LPSTR)"Can't start MATLAB engine!", (LPSTR) "MatLab Engine: ERROR!", MB_OK | MB_ICONSTOP);
return;
};
return;
}
void StopedVirtualEngineMatlab()
{
engClose(pEng);
return;
}
DLLWRAP_API bool TestDll()
{
if (pEng == NULL) return false;
return true;
}
DLLWRAP_API void MyFigure()
{
engEvalString(pEng, "myfig();");
}
dllmain.cpp
#include "stdafx.h"
#include "dllwrap.h"
extern Engine* pEng;
extern void StartVirtualEngineMatlab();
extern void StopedVirtualEngineMatlab();
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
StartVirtualEngineMatlab();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
StopedVirtualEngineMatlab();
break;
}
return TRUE;
}
Now I am in focus on a Test project (C# Console Application) to call a m-files through dll-wraper.
Test.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace Test
{
class Program
{
[DllImport("dllwrap.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool TestDll();
[DllImport("dllwrap.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MyFigure();
static void Main(string[] args)
{
bool res = TestDll();
if (res == false)
return;
MyFigure();
}
}
}
The Test project is running and doing the job, but there is a problem. A Matlab Engine crashes in unexpected time. It may crash at the begining or after a while. I even tried to stop on breaking point right after the engOpen(NULL) function, but the crashing is seems not depending on my break.
I use Visual Studio 2013, Matlab 2015a 32bit.
Please help in advise.
Thanks.
Ok, I found the problem.
I just removed the line:
StopedVirtualEngineMatlab();
from dllmain.cpp
case DLL_PROCESS_DETACH:
StopedVirtualEngineMatlab();
break;
}
and put it as external funtion to call it from the end of the code of Test.cs.
Now it works perfect.
But still I don't understand why the DLL_PROCESS_DETACH case is invoked...?
Related
I'm able to call function from DLL created in C (.c file), but i can't do it from DLL created in C++ (.cpp file). I want to find out why it doesn't work in .cpp file.
I'm trying to call function printword() from a simple DLL, created with Visual Studio 2022:
// FILE: dllmain.cpp
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
__declspec(dllexport) void printword() {
std::cout << "word" << std::endl; //with printf() doesn't work too
}
And when i call function the way like this:
int main() {
HMODULE dll;
if ((dll = LoadLibrary(L"D:\\Visual Studio projects\\Dll1\\x64\\Debug\\Dll1.dll")) == NULL) {
return GetLastError();
}
FARPROC func;
if ((func = GetProcAddress(dll, "printword")) == NULL) {
return GetLastError();
}
func();
return 0;
}
GetProcAddress throws error ERROR_PROC_NOT_FOUND
But if i create DLL in file with .c suffix printword() function calls correctly (with same code above):
// FILE: dllmain.c
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
__declspec(dllexport) void printword() {
printf("word\n");
}
The exported function's name will get mangled when the DLL is compiled. You must use the mangled name in GetProcAddress() in order for it to work. For example, the mangled name
in MSVC is:
GetProcAddress(dll, "?printword##YAXXZ");
Or, you could add this to the function's body to tell the compiler not to mangle it:
__declspec(dllexport) void printword() {
#pragma comment(linker, "/EXPORT:" __FUNCTION__"=" __FUNCDNAME__)
printf("word\n");
}
Alternatively, adding extern "C" will also solve the problem.
Review and try the recommendations from this article:
https://learn.microsoft.com/sr-cyrl-rs/cpp/build/exporting-cpp-functions-for-use-in-c-language-executables?view=msvc-170
Example
// MyCFuncs.h
extern "C" __declspec( dllexport ) int MyFunc(long parm1);
Key part being extern "C"
[I accidentally posted the link for importing instead of exporting earlier - corrected for the export article]
I have created this dll in Go with an exported function which works fine while I'm calling it with rundll32 or from a c++ executable with the loadlbraryA. But I get an error when calling from c++ dll which I tried to read GetLastError() And it says cannot find the module you are calling. I tried every possible way to give the full path to loadlibraryA but the same error happens and the handle to Go DLL is null every time. Also, I examined the Go DLL, and the Test function is exported properly.
In short, It works in calling Test():
From rundll32
From c++ main() and loadlibrary
And doesn't work in Test():
From c++ DllMain() and loadlibrary
From c++ DllMain() and loadlibrary directly called from kernel32.dll
From c++ DllMain() and a ThreadFunction created in DllMain()
Folder structure
ProjectFolder
-- main.go
-- dllmain.h
-- dllmain.go
Build with
go build -buildmode=c-shared -o my-go-library.dll main.go
Call example dll
rundll32 my-go-library.dll Test
Working source
main.go:
package main
import "C"
import (
"syscall"
"time"
"unsafe"
)
//export Test
func Test() {
MessageBoxPlain("TestMsgbox","Test")
main()
}
//export OnProcessAttach
func OnProcessAttach() {
MessageBoxPlain("OnAttachMsgbox","OnAttach")
Test()
}
// MessageBox of Win32 API.
func MessageBox(hwnd uintptr, caption, title string, flags uint) int {
ret, _, _ := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call(
uintptr(hwnd),
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(caption))),
uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(title))),
uintptr(flags))
return int(ret)
}
// MessageBoxPlain of Win32 API.
func MessageBoxPlain(title, caption string) int {
const (
NULL = 0
MB_OK = 0
)
return MessageBox(NULL, caption, title, MB_OK)
}
func main() {}
dllmain.h:
#include <windows.h>
void OnProcessAttach(HINSTANCE, DWORD, LPVOID);
typedef struct {
HINSTANCE hinstDLL; // handle to DLL module
DWORD fdwReason; // reason for calling function // reserved
LPVOID lpReserved; // reserved
} MyThreadParams;
DWORD WINAPI MyThreadFunction(LPVOID lpParam) {
MyThreadParams params = *((MyThreadParams*)lpParam);
OnProcessAttach(params.hinstDLL, params.fdwReason, params.lpReserved);
free(lpParam);
return 0;
}
BOOL WINAPI DllMain(
HINSTANCE _hinstDLL, // handle to DLL module
DWORD _fdwReason, // reason for calling function
LPVOID _lpReserved) // reserved
{
switch (_fdwReason) {
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
{
MyThreadParams* lpThrdParam = (MyThreadParams*)malloc(sizeof(MyThreadParams));
lpThrdParam->hinstDLL = _hinstDLL;
lpThrdParam->fdwReason = _fdwReason;
lpThrdParam->lpReserved = _lpReserved;
HANDLE hThread = CreateThread(NULL, 0, MyThreadFunction, lpThrdParam, 0, NULL);
// CreateThread() because otherwise DllMain() is highly likely to deadlock.
}
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
}
return TRUE; // Successful.
}
dllmain.go:
package main
//#include "dllmain.h"
import "C"
C++ DLL
Now the c++ dll source which calls Test from my-go-library.dll:
#include "pch.h"
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winternl.h>
#include <malloc.h>
#include <intrin.h>
#include <Windows.h>
#include <winternl.h>
#include <malloc.h>
#include <ostream>
#include <iostream>
#include <string>
using namespace std;
typedef int(__stdcall* TestFromGo)();
void Error()
{
wchar_t err[256];
memset(err, 0, 256);
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err, 255, NULL);
int msgboxID = MessageBoxW(NULL,err,(LPCWSTR)L"Error",MB_OK);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
MessageBoxA(0, "The C++ DLL", "title", 0);
HINSTANCE hGetProcIDDLL = LoadLibraryA("C:\\User\\.....path to go dll.....\\my-go-library.dll");
if (!hGetProcIDDLL) {
Error();
MessageBoxA(0, "could not load the dynamic library", "Test", 0);
}
TestFromGo TestFunction = (TestFromGo)GetProcAddress(hGetProcIDDLL, "Test");
if (!TestFunction) {
MessageBoxA(0, "could not locate the function", "Test", 0);
}
TestFromGo();
}
extern "C" __declspec(dllexport) void jojo()
{
DllMain(0, 1, 0);
}
Calling the c++ dll
Now this one supposed to call jojo then DllMain then calling my-go-library.dll and Test
rundll32 theCiplasplas.dll jojo
I can't help with Golang. But there are problems in your DllMain. There are only a limited set of API functions allowed in DllMain.
The Dynamic-Link Library Best Practices explicitly states that you should not create a thread in DllMain:
You should never perform the following tasks from within DllMain:
Call CreateThread. Creating a thread can work if you do not synchronize with other threads, but it is risky.
Call LoadLibrary or LoadLibraryEx (either directly or indirectly). This can cause a deadlock or a crash
So it might work when you use rundll32, it might not work if you load your DLL in another way.
Edit : Added excerpt about LoadLibrary
I'm trying to inject a simple executable into another executable that I made, unfortunately, whenever I inject the code into the executable, it says 'simpleinjected.exe has stopped working' then it closes. I'm using CreateRemoteThread to inject the code. This is what I have done so far.
Injector.exe // the file that's injecting the code
#include <stdio.h>
#include <windows.h>
#define procId 2844
#define executable "executable.exe" // located in same directory
int main()
{
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, false, procId);
LPVOID allocated = (LPVOID)VirtualAllocEx(hProc, NULL, strlen(executable), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProc, (LPVOID)allocated, executable, strlen(executable), NULL);
LPVOID libaddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)libaddr, NULL, NULL);
CloseHandle(hProc);
return 0;
}
Simpleinjected.exe // the file being injected
#include <stdio.h>
int main()
{
printf("Hello");
return 0;
}
executable.exe // the executable being injected into simpleinjected
#include <windows.h>
int main()
{
MessageBox(NULL, "Injected successfully", "Code Injection", MB_OK);
return 0;
}
The message is not displaying and simpleinjected.exe crashes. The crash shows that the code was inserted but I don't understand why it's crashing.
When using DLL and the same technique above, the dll executes in the 'simpleinjected.exe' but doesn't work when injected into Firefox. The dll code is below. It executes in the custom application but not Firefox even though it's injected successfully.
dllinject.dll
#include <windows.h>
int message(const char *msg)
{
MessageBox(NULL, msg, "Message from Dll", MB_OK);
return 0;
}
BOOL WINAPI DLLMain(HINSTANCE hInstDll, DWORD ulReason, LPVOID lpReserved)
{
switch(ulReason)
{
case DLL_PROCESS_ATTACH:
message("process attach");
break;
case DLL_THREAD_ATTACH:
message("thread attach");
break;
case DLL_PROCESS_DETACH:
message("process detach");
break;
case DLL_THREAD_DETACH:
message("thread detach");
break;
}
return true;
}
modified code of Simpleinjected.exe as these below. and then try inject dllinject.dll to Simpleinjected.exe again.
#include <stdio.h>
int main()
{
while(true)
{
printf("Hello");
}
return 0;
}
you should modify the defines below as same as Simpleinjected.exe.
#define procId 2844 //process id of Simpleinjected.exe
#define executable "dllinject.dll" // located in same directory
Im trying to return the array of double (declared as double*) to delphi program. In c++ dll project I have
#define DllExport __declspec( dllexport )
extern double* array;
extern "C"
{
DllExport double* SomeMethod(double);
}
and array got deleted when Dll is unloaded
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch( ul_reason_for_call )
{
...
case DLL_PROCESS_DETACH:
delete [] array;
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
While I was testing my dll in c++ console application I got the right result after using SomeMethod from dll. Next i tried to test my dll in Delphi but the content of array returned by method is wrong. I used the following code.
TSomeMethod = function(level : Double): PDouble; cdecl;
...
var
SomeMethod: TSomeMethod;
arr: PDouble;
...
if Assigned(SomeMethod) then
begin
arr:= SomeMethod(15);
writeln(arr^:2:0);
inc(arr);
writeln(arr^:2:0);
end
...
What is a proper way to return a double* from c++ dll to use in delphi?
P.S. Other methods work in th right way. For example dll returns char* and in delphi I got it using PAnsiChar
UPDATE
Here is some C++ code from file where SomeMethod is written.
double* array; // yea it's an array that declared as external in other file;
...
double* SomeMethod(double level)
{
...
deque<double> arrayToReturn;
... // some actions with deque
array= new double[arrayToReturn.size()];
for (unsigned int i = 0; i<arrayToReturn.size(); i++)
array[i] = arrayToReturn[i];
return array;
}
The code in your question works fine. Which means that the problem lies elsewhere. Here's the proof:
C++
#include <Windows.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C" {
__declspec(dllexport) double* SomeMethod(double)
{
double* array = new double[2];
array[0] = 42;
array[1] = 666;
return array;
}
}
Delphi
{$APPTYPE CONSOLE}
uses
Windows, SysUtils;
type
TSomeMethod = function(level : Double): PDouble; cdecl;
var
SomeMethod: TSomeMethod;
arr: PDouble;
lib: HMODULE;
begin
lib := LoadLibrary('MyDll.dll');
Win32Check(lib<>0);
SomeMethod := GetProcAddress(lib, 'SomeMethod');
Win32Check(Assigned(SomeMethod));
arr:= SomeMethod(15);
Writeln(arr^:3:0);
inc(arr);
Writeln(arr^:3:0);
Readln;
end.
Output
42
666
I am hooking FindNextFile() using MS Detours. I have configured the Detours library successfully and wrote a dll named "Detuors.dll" and an application named "FNFSend.exe". The following is the code:
DLL:
#include <cstdio>
#include <stdio.h>
#include <windows.h>
#include "detours.h"
#pragma comment (lib,"detours.lib")
//Prototypes
extern "C" __declspec(dllexport) BOOL (WINAPI *pFNF)(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData) = FindNextFile;
extern "C" __declspec(dllexport) BOOL WINAPI MyFNF(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData);
//Log File
FILE* pFNFLogFile;
int counter = 0;
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hDLL);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pFNF, MyFNF);
if(DetourTransactionCommit() == NO_ERROR)
OutputDebugString("FNF() detoured successfully");
else
OutputDebugString("FNF() not detoured");
break;
case DLL_PROCESS_DETACH:
DetourTransactionBegin(); //Detach
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)pFNF, MyFNF);
DetourTransactionCommit();
break;
case DLL_THREAD_ATTACH:
DisableThreadLibraryCalls(hDLL);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pFNF, MyFNF);
if(DetourTransactionCommit() == NO_ERROR)
OutputDebugString("FNF() detoured successfully");
else
OutputDebugString("FNF() not detoured");
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
//Open file, write contents, close it
extern "C" __declspec(dllexport) int WINAPI MyFNF(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData)
{
counter ++;
fopen_s(&pFNFLogFile, "C:\\FNFLog.txt", "a+");
fprintf(pFNFLogFile, "%s\n", counter);
fclose(pFNFLogFile);
return pFNF(hFindFile, lpFindFileData);
}
Both the codes compiled successfully with no errors. The application calls FindNextFile() recursively and the dll hooks it and write the counter to a file.
I then used the tool named "withdll.exe" that is provided by detours library itself to create a process with a dll injected in it. So I injected my dll into the application using command:
withdll /d:Detuors.dll "C:\FNFSend.exe"
After injection, the function is hooked successfully, i.e. the file is made in the dirctory but suddenly the application crashes. After debugging in visual studio, I saw the exception in "output.c" as follows:
Unhandled exception at 0x6265984f (msvcr90d.dll) in FNFSend.exe: 0xC0000005:
Access violation reading location 0x00000001.
Kindly help in rectifying the problem.
%s is not a valid format string for printing out a number. Use %d instead.
By specifying %s you're telling fprintf to read the memory at address counter as a string. The first value you try calling fprintf with is 1 which is why there is an access violation at address 0x00000001.