Im trying to load a dll I wrote in c++ to do some memory accessing for me into a python program Im writing. below are the header file and the cpp file of the dll:
//MemoryReader.h
#pragma once
#ifdef MEMORYREADER_EXPORTS
#define MEMORYREADER_API __declspec(dllexport)
#else
#define MEMORYREADER_API __declspec(dllimport)
#endif
#include <Windows.h>
#include <vector>
extern "C" MEMORYREADER_API DWORD GetModuleBaseAddress(TCHAR * lpszModuleName, DWORD pID);
extern "C" MEMORYREADER_API int GetAddressRaw(DWORD baseAdd, DWORD* offsetsBase, int size);
extern "C" MEMORYREADER_API int GetAddress(DWORD baseAdd, std::vector<DWORD> offsets);
//MemoryReader.cpp
#include <Windows.h>
#include "pch.h"
#include<TlHelp32.h>
#include <iostream>
#include <tchar.h> // _tcscmp
#include <vector>
DWORD GetModuleBaseAddress(TCHAR* lpszModuleName, DWORD pID)
{
DWORD dwModuleBaseAddress = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID); // make snapshot of all modules within process
MODULEENTRY32 ModuleEntry32 = { 0 };
ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
if (Module32First(hSnapshot, &ModuleEntry32)) //store first Module in ModuleEntry32
{
do {
if (_tcscmp(ModuleEntry32.szModule, lpszModuleName) == 0) // if Found Module matches Module we look for -> done!
{
dwModuleBaseAddress = (DWORD)ModuleEntry32.modBaseAddr;
break;
}
} while (Module32Next(hSnapshot, &ModuleEntry32)); // go through Module entries in Snapshot and store in ModuleEntry32
}
CloseHandle(hSnapshot);
return dwModuleBaseAddress;
}
int GetAddress(DWORD baseAdd, std::vector<DWORD> offsets)
{
DWORD offsetGameToBaseAdress = baseAdd;
std::vector<DWORD> pointsOffsets = offsets;
HWND hGameWindow = FindWindow(NULL, "Trackmania");
if (hGameWindow == NULL) {
std::cout << "Start the game!" << std::endl;
return 0;
}
DWORD pID = NULL; // ID of our Game
GetWindowThreadProcessId(hGameWindow, &pID);
HANDLE processHandle = NULL;
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
if (processHandle == INVALID_HANDLE_VALUE || processHandle == NULL) { // error handling
std::cout << "Failed to open process" << std::endl;
return 0;
}
char gameName[] = "Trackmania.exe";
DWORD gameBaseAddress = GetModuleBaseAddress(_T(gameName), pID);
DWORD baseAddress = NULL;
//Get value at gamebase+offset -> store it in baseAddress
ReadProcessMemory(processHandle, (LPVOID)(gameBaseAddress + offsetGameToBaseAdress), &baseAddress, sizeof(baseAddress), NULL);
std::cout << "debugginfo: baseaddress = " << std::hex << baseAddress << std::endl;
DWORD targetAddress = baseAddress; //the Adress we need -> change now while going through offsets
for (int i = 0; i < pointsOffsets.size() - 1; i++) // -1 because we dont want the value at the last offset
{
ReadProcessMemory(processHandle, (LPVOID)(targetAddress + pointsOffsets.at(i)), &targetAddress, sizeof(targetAddress), NULL);
std::cout << "debugginfo: Value at offset = " << std::hex << targetAddress << std::endl;
}
targetAddress += pointsOffsets.at(pointsOffsets.size() - 1); //Add Last offset -> done!!
return targetAddress;
}
int GetAddressRaw(DWORD baseAdd, DWORD* offsetsBase, int size)
{
std::vector<DWORD> offsets(offsetsBase, offsetsBase + size);
DWORD targetAddress = GetAddress(baseAdd, offsets);
return targetAddress;
}
This all compiles fine and I built the dll and saved it into the project folder. This is the python code using ctypes to load the dll:
import ctypes
from ctypes import wintypes
from ctypes import cdll
readerDll = cdll.LoadLibrary('C:/Users/owenc/Documents/GitHub/TrackManiaRL/TrackmaniaActorCritic/MemoryReader/MemoryReader.dll')
def process_addresses(base_address, offsets):
p1 = ctypes.wintypes.DWORD(int(base_address, 16))
p2 = ctypes.c_char_p(offsets.encode('utf-8'))
p3 = ctypes.c_int(len(offsets))
address = readerDll.GetAddressRaw(p1, p2, p3)
input(address)
return address
the problem is that this code is throwing this error:
Traceback (most recent call last):
File "C:/Users/owenc/Documents/GitHub/TrackManiaRL/TrackmaniaActorCritic/main.py", line 29, in <module>
env = TrackmaniaEnv(speed_address, checkpoint_address, goal_address, VAEncoder)
File "C:\Users\owenc\Documents\GitHub\TrackManiaRL\TrackmaniaActorCritic\environment.py", line 58, in __init__
self.speed_address = process_addresses(spd_address, self.speed_offset)
File "C:\Users\owenc\Documents\GitHub\TrackManiaRL\TrackmaniaActorCritic\environment.py", line 45, in process_addresses
address = readerDll.GetAddressRaw(p1, p2, p3)
File "C:\Users\owenc\anaconda3\envs\tf-gpu\lib\ctypes\__init__.py", line 377, in __getattr__
func = self.__getitem__(name)
File "C:\Users\owenc\anaconda3\envs\tf-gpu\lib\ctypes\__init__.py", line 382, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'GetAddressRaw' not found
Ive tried looking into the problem, but it seems like most people that get this error have simply accidentally left out the exern "C" or the __declspec(dllexport) in their c++ code. Ive tried a few variations on the python code, but I cant seem to find out why the function isnt being found.
Hopefully theres someone who knows ctypes well who can give me a hand here.