The exception message tells you the answer:
ValueError: Procedure called with not enough arguments (12 bytes missing) or wrong calling convention
The number of arguments is right, so it must be the other: You are using the wrong calling convention. The calling convention is the way the compiler maps the three arguments in C into a way to store the actual values in memory when calling the function (among a few other things). On the MSDN documentation for GetModuleFileA you find the following signature
DWORD WINAPI GetModuleFileName(
_In_opt_ HMODULE hModule,
_Out_ LPTSTR lpFilename,
_In_ DWORD nSize
);
The WINAPI
tells the compiler to use the stdcall
calling convention. Your ctypes code uses cdll
which on the other hand assumes cdecl
calling convetion. The solution is simple: change cdll
to windll
:
from ctypes import *
path=create_string_buffer(256)
rs=windll.Kernel32.GetModuleFileNameA(0,path,256)
print (path)
Compare with the ctypes documentation for accessing .dll's, where kernel32
is explicitely shown to use windll
.