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
Answer from Mark Tolonen on Stack OverflowI 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
Basically this other answer, but closer to the question:
import ctypes
class Root(ctypes.Structure):
_fields_ = [("foo", ctypes.c_bool)]
class Kotlin(ctypes.Structure):
_fields_ = [("root", Root)]
class Libnative_ExportedSymbols(ctypes.Structure):
_fields_ = [("kotlin", Kotlin)]
libPath = "path/to/libnative.dll"
dll = ctypes.CDLL(libPath)
dll.libnative_symbols.restype = ctypes.POINTER(Libnative_ExportedSymbols)
libnative = dll.libnative_symbols().contents
print(type(libnative.kotlin.root)) # <class '__main__.Root'>
print(libnative.kotlin.root) # <__main__.Root object at ...
Note that the following approach without POINTER would also work, but may cause errors down the road:
dll.libnative_symbols.restype = Libnative_ExportedSymbols
libnative = dll.libnative_symbols()
print(type(libnative.kotlin.root)) # <class '__main__.Root'>
print(libnative.kotlin.root) # <__main__.Root object at ...
python - How to return a pointer to a structure in ctypes? - Stack Overflow
How to access data from pointer in struct from Python with ctypes? - Stack Overflow
struct - C-like structures in Python - Stack Overflow
Accessing struct data through a pointer in a Python C extension - Stack Overflow
Change
foo = POINTER(temp_foo)
to
foo = pointer(temp_foo)
can solve the problem.
Please see http://docs.python.org/library/ctypes.html#ctypes-pointers for more information.
Your bar function has an incorrect definition, I guess you mean it is struct FOO_ *bar(int);?
The Python code is wrong in the sense that foo_parameter is never declared, so I'm not 100% sure what you want to do. I assume you want to pass a parameter of your python-declared foo, which is an instance of a struct FOO_, into the C bar(int) and get back a pointer to struct FOO_.
You don't need POINTER to do that, the following will work:
#!/usr/bin/env python
from ctypes import *
class foo(Structure):
_fields_=[("i",c_int),
("b1",POINTER(c_int)),
("w1",POINTER(c_float))]
myclib = cdll.LoadLibrary("./libexample.so")
temp_foo = foo(1,None,None)
foovar = myclib.bar(temp_foo.i)
myclib.foo_write(foovar)
Since CTypes will wrap the return type of bar() in a pointer-to-struct for you.
Well there are some mistakes in the above code.
Need to pass the pointer address as an unsigned long/int to the python module. So
void getmodelparam(long pModelParam)
//has to become
void getmodelparam(unsigned long pModelParam)
//and
PyObject *pResult = PyObject_CallFunction(pFunc,"i", pModelParam) ;
// has to become
PyObject *pResult = PyObject_CallFunction(pFunc,"k", pModelParam) ;
and then in the python file:
def modifymodelparam(m):
n = ctypes.cast(m, ctypes.POINTER(someTime))
print (n.contents.seconds)
print (n.contents.nanoseconds)
To typecast, cast function can be used
n = ctypes.cast(m, someTime)
[Google]http://docs.python.org/2/library/ctypes.html