This is a snippet from a C header for a Windows DLL that was generated by Kotlin Multiplatform/Native:
typedef struct {
struct {
struct {
// ...
} root;
} kotlin;
} libnative_ExportedSymbols;
extern libnative_ExportedSymbols* libnative_symbols(void);
From C, you would access the struct root
like this:
libnative_ExportedSymbols* lib = libnative_symbols();
lib->kotlin.root. // ...
How can I access it from Python? It seems that all official samples have been removed. So I tried this without success:
import ctypes
libPath = "path/to/libnative.dll"
dll = ctypes.CDLL(libPath)
pythonInt = dll.libnative_symbols()
print(type(pythonInt)) # <class 'int'>
print(pythonInt) # A number, e.g. 1190351680
CPointer = ctypes.POINTER(ctypes.c_long)
cLong = ctypes.c_long(pythonInt)
cAddress = ctypes.addressof(cLong)
cPointer = ctypes.cast(cAddress, CPointer)
print(type(pythonInt) == type(cPointer.contents.value)) # true
print(pythonInt == cPointer.contents.value) # true
try:
print(cPointer.kotlin.root)
except AttributeError:
print("AttributeError") # AttributeError
try:
print(cPointer.contents.kotlin.root)
except AttributeError:
print("AttributeError") # AttributeError
try:
print(cPointer.contents.value.kotlin.root)
except AttributeError:
print("AttributeError") # AttributeError
I don't know anything about Kotlin, but given the C structure described here's a C DLL with that structure and the Python code to call it. The structures need to be derived from ctypes.Structure
and the return type of the function needs to be declared via .restype
and not left to the default of (usually 32-bit) integer. Casting the return value after-the-fact is too late if it was meant to be a 64-bit pointer.
test.c
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
typedef struct {
struct {
struct {
int a;
} root;
} kotlin;
} libnative_ExportedSymbols;
libnative_ExportedSymbols g_lib = {7};
API libnative_ExportedSymbols* libnative_symbols(void) {
return &g_lib;
}
test.py
import ctypes as ct
class Root(ct.Structure):
_fields_ = ('a', ct.c_int),
class Kotlin(ct.Structure):
_fields_ = ('root', Root),
class Symbols(ct.Structure):
_fields_ = ('kotlin', Kotlin),
dll = ct.CDLL('./test')
dll.libnative_symbols.argtypes = ()
dll.libnative_symbols.restype = ct.POINTER(Symbols)
lib = dll.libnative_symbols()
print(lib.contents.kotlin.root.a)
Output:
7