如何调用动态分配 python 方法到从共享库导出的 C 指针函数
how to call assign dynamically a python method to a C pointer function exported from a shared library
我想解决以下问题。共享库中的某些 C 代码将调用指针函数,该函数是共享库的导出符号
#include <stdio.h>
typedef void (*pCallBack)(const char *);
pCallBack one_pointer;
void errorPrint(const char * str)
{
printf("my address = %p", one_pointer);
fflush(stdout);
(*one_pointer)(str);
}
让我们将该库编译为共享库
gcc -fPIC -g -shared -o call_back.so call_back.c
现在我想从 Python 调用它,动态重新定义 pCallBack
指针的实现
import ctypes
import sys
def myCallBack(str):
print("inside python" % str)
sys.stdout.flush()
libcallback = ctypes.CDLL("./call_back.so")
pointer_CallBack = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p)
libcallback.one_pointer = pointer_CallBack(myCallBack)
libcallback.errorPrint(b"one_string")
不幸的是,导出的数据指针似乎无法重新定义。我也尝试了 ctypes
中的 in_dll
函数,但它没有解决问题
当尝试 运行 我的 Python 脚本时,我得到以下内容
LD_PRELOAD="./call_back.so" python3 error.py
my address = (nil)[1] 2871869 segmentation fault (core dumped)
有人知道这个问题吗?
清单[Python.Docs]: ctypes - A foreign function library for Python.
使用ct.in_dll修改.dll中的变量适用于简单类型(int).我不知道如何(干净地)为(函数)指针执行此操作。因此,您需要一个简单设置回调的新函数。
还有一些错误:
- 否 NULL 签入 errorPrint
- argtypes 和 restype 未设置导出函数。有关
的更多详细信息
- 回调函数返回 void(不是 void*)
这是一个工作示例。
dll00.c:
#include <stdio.h>
#if defined(_WIN32)
# define DLL00_EXPORT_API __declspec(dllexport)
#else
# define DLL00_EXPORT_API
#endif
typedef void (*CallbackFuncPtr)(const char*);
#if defined(__cplusplus)
extern "C" {
#endif
DLL00_EXPORT_API void setCallback(CallbackFuncPtr cb);
DLL00_EXPORT_API void errorPrint(const char *str);
#if defined(__cplusplus)
}
#endif
CallbackFuncPtr callback = NULL;
void setCallback(CallbackFuncPtr cb) {
callback = cb;
}
void errorPrint(const char * str) {
printf("C - Callback: %p\n", callback);
fflush(stdout);
if (callback) {
(*callback)(str);
}
printf("C - done\n");
}
code00.py
#!/usr/bin/env python
import sys
import ctypes as ct
DLL_NAME = "./dll00.so"
CallBackType = ct.CFUNCTYPE(None, ct.c_char_p)
def callback_func(s):
print("PY - callback arg: {:}".format(s))
sys.stdout.flush()
def main(*argv):
dll00 = ct.CDLL(DLL_NAME)
setCallback = dll00.setCallback
setCallback.argtypes = (CallBackType,)
setCallback.restype = None
errorPrint = dll00.errorPrint
errorPrint.argtypes = (ct.c_char_p,)
errorPrint.restype = None
cb = CallBackType.in_dll(dll00, "callback")
print("Original callback: {:}".format(cb))
callback = CallBackType(callback_func)
print("New callback: {:}\n".format(callback))
errorPrint(b"Before setting callback")
setCallback(callback)
errorPrint(b"After setting callback")
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
输出:
[cfati@cfati-5510-0:/mnt/e/Work/Dev/Whosebug/q067079630]> ~/sopr.sh
*** Set shorter prompt to better fit when pasted in Whosebug (or other) pages ***
[064bit prompt]> ls
code00.py dll00.c
[064bit prompt]> gcc -shared -fPIC -o dll00.so dll00.c
[064bit prompt]> ls
code00.py dll00.c dll00.so
[064bit prompt]>
[064bit prompt]> python code00.py
Python 3.8.5 (default, Jan 27 2021, 15:41:15) [GCC 9.3.0] 64bit on linux
Original callback: <CFunctionType object at 0x7f07ef740ac0>
New callback: <CFunctionType object at 0x7f07ef740e80>
C - Callback: (nil)
C - done
C - Callback: 0x7f07efffc010
PY - callback arg: b'After setting callback'
C - done
Done.
我想解决以下问题。共享库中的某些 C 代码将调用指针函数,该函数是共享库的导出符号
#include <stdio.h>
typedef void (*pCallBack)(const char *);
pCallBack one_pointer;
void errorPrint(const char * str)
{
printf("my address = %p", one_pointer);
fflush(stdout);
(*one_pointer)(str);
}
让我们将该库编译为共享库
gcc -fPIC -g -shared -o call_back.so call_back.c
现在我想从 Python 调用它,动态重新定义 pCallBack
指针的实现
import ctypes
import sys
def myCallBack(str):
print("inside python" % str)
sys.stdout.flush()
libcallback = ctypes.CDLL("./call_back.so")
pointer_CallBack = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p)
libcallback.one_pointer = pointer_CallBack(myCallBack)
libcallback.errorPrint(b"one_string")
不幸的是,导出的数据指针似乎无法重新定义。我也尝试了 ctypes
中的 in_dll
函数,但它没有解决问题
当尝试 运行 我的 Python 脚本时,我得到以下内容
LD_PRELOAD="./call_back.so" python3 error.py
my address = (nil)[1] 2871869 segmentation fault (core dumped)
有人知道这个问题吗?
清单[Python.Docs]: ctypes - A foreign function library for Python.
使用ct.in_dll修改.dll中的变量适用于简单类型(int).我不知道如何(干净地)为(函数)指针执行此操作。因此,您需要一个简单设置回调的新函数。
还有一些错误:
- 否 NULL 签入 errorPrint
- argtypes 和 restype 未设置导出函数。有关
- 回调函数返回 void(不是 void*)
这是一个工作示例。
dll00.c:
#include <stdio.h>
#if defined(_WIN32)
# define DLL00_EXPORT_API __declspec(dllexport)
#else
# define DLL00_EXPORT_API
#endif
typedef void (*CallbackFuncPtr)(const char*);
#if defined(__cplusplus)
extern "C" {
#endif
DLL00_EXPORT_API void setCallback(CallbackFuncPtr cb);
DLL00_EXPORT_API void errorPrint(const char *str);
#if defined(__cplusplus)
}
#endif
CallbackFuncPtr callback = NULL;
void setCallback(CallbackFuncPtr cb) {
callback = cb;
}
void errorPrint(const char * str) {
printf("C - Callback: %p\n", callback);
fflush(stdout);
if (callback) {
(*callback)(str);
}
printf("C - done\n");
}
code00.py
#!/usr/bin/env python
import sys
import ctypes as ct
DLL_NAME = "./dll00.so"
CallBackType = ct.CFUNCTYPE(None, ct.c_char_p)
def callback_func(s):
print("PY - callback arg: {:}".format(s))
sys.stdout.flush()
def main(*argv):
dll00 = ct.CDLL(DLL_NAME)
setCallback = dll00.setCallback
setCallback.argtypes = (CallBackType,)
setCallback.restype = None
errorPrint = dll00.errorPrint
errorPrint.argtypes = (ct.c_char_p,)
errorPrint.restype = None
cb = CallBackType.in_dll(dll00, "callback")
print("Original callback: {:}".format(cb))
callback = CallBackType(callback_func)
print("New callback: {:}\n".format(callback))
errorPrint(b"Before setting callback")
setCallback(callback)
errorPrint(b"After setting callback")
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
输出:
[cfati@cfati-5510-0:/mnt/e/Work/Dev/Whosebug/q067079630]> ~/sopr.sh *** Set shorter prompt to better fit when pasted in Whosebug (or other) pages *** [064bit prompt]> ls code00.py dll00.c [064bit prompt]> gcc -shared -fPIC -o dll00.so dll00.c [064bit prompt]> ls code00.py dll00.c dll00.so [064bit prompt]> [064bit prompt]> python code00.py Python 3.8.5 (default, Jan 27 2021, 15:41:15) [GCC 9.3.0] 64bit on linux Original callback: <CFunctionType object at 0x7f07ef740ac0> New callback: <CFunctionType object at 0x7f07ef740e80> C - Callback: (nil) C - done C - Callback: 0x7f07efffc010 PY - callback arg: b'After setting callback' C - done Done.