我在NASM中编写了一个dll,使用ctypes从Python调用。我在我的ctypes包装器中创建了一个简短的Python回调程序:
def LibraryCall(a):
b = math.ceil(a)
return b
我知道dll调用回调函数,因为当我单步执行ctypes包装时,光标跳转到回调函数,执行回调,并返回再次调用dll,这似乎是问题所在。
Python ctypes代码是:
def SimpleTestFunction_asm(X):
Input_Length_Array = []
Input_Length_Array.append(len(X))
CA_X = (ctypes.c_double * len(X))(*X)
length_array_out = (ctypes.c_double * len(Input_Length_Array)) (*Input_Length_Array)
hDLL = ctypes.WinDLL ("C:/Test_Projects/SimpleTestFunction/SimpleTestFunction.dll")
CallName = hDLL.Main_Entry_fn
CallName.argtypes = [ctypes.POINTER (ctypes.c_double),ctypes.POINTER(ctypes.c_double),ctypes.POINTER (ctypes.c_longlong)]
CallName.restype = ctypes.c_int64
#__________
#The callback function
LibraryCB = ctypes.WINFUNCTYPE(ctypes.c_double, ctypes.c_double)
def LibraryCall(a): #CALLBACK FUNCTION IN PYTHON
b = math.ceil(a)
return b
lib_call = LibraryCB(LibraryCall)
lib_call = ctypes.cast(lib_call,ctypes.POINTER(ctypes.c_longlong))
#__________
ret_ptr = CallName(CA_X, length_array_out, lib_call) ; CALL TO DLL
a = ret_ptr[:2]
n0 = ctypes.cast(a[0],ctypes.POINTER(ctypes.c_double))
n0_size = int(a[0+1] / 8)
x0 = n0[:n0_size]
当我单步执行程序时,现在发生的是光标从标记为“CALL TO DLL”的行跳转到标记为“PYTHON中的CALLBACK FUNCTION”的行。它正确执行Python回调程序,然后光标跳回标记为“CALL TO DLL”的行,此时它崩溃而没有错误消息。它似乎返回再次调用DLL,但我希望它执行回调函数并将结果返回到已调用的DLL。
以下是简单的NASM测试代码:
; Header Section
[BITS 64]
[default rel]
export Main_Entry_fn
export FreeMem_fn
extern malloc, realloc, free
section .data align=16
[DATA SECTION OMITTED FOR BREVITY]
section .text
SimpleTestFunction_fn:
xor rcx,rcx
mov [loop_counter_401],rcx
label_401:
lea rdi,[rel X_ptr]
mov rbp,qword [rdi] ; Pointer
mov rcx,[loop_counter_401]
mov rax,[X_length]
cmp rcx,rax
jge exit_label_for_SimpleTestFunction_fn
movsd xmm0,qword[rbp+rcx]
movsd [x_var],xmm0
;______
movsd xmm1,[const_40]
mulsd xmm0,xmm1
movsd [a],xmm0
movsd xmm0,[a]
call [CB_Pointer] ; THIS IS THE CALL TO THE CALLBACK FUNCTION
movsd [b],xmm0
ret
;__________
;Free the memory
FreeMem_fn:
;The pointer is passed back in rcx (of course)
sub rsp,40
call free
add rsp,40
ret
; __________
; Main Entry
Main_Entry_fn:
push rdi
push rbp
mov [X_ptr],rcx
mov [data_master_ptr],rdx
mov [CB_Pointer],r8
; Now assign lengths
lea rdi,[data_master_ptr]
mov rbp,[rdi]
xor rcx,rcx
movsd xmm0,qword[rbp+rcx]
cvttsd2si rax,xmm0
mov [X_length],rax
add rcx,8
; __________
; malloc for dynamic arrays
lea rdi,[data_master_ptr]
mov rbp,[rdi]
movsd xmm0,qword[rbp]
cvttsd2si rax,xmm0
mov [initial_dynamic_length],rax
mov rcx,qword[initial_dynamic_length] ; Initial size
xor rax,rax
sub rsp,40
call malloc
mov qword [collect_ptr],rax
add rsp,40
mov rax,[initial_dynamic_length]
mov [collect_length],rax
; __________
call SimpleTestFunction_fn
exit_label_for_Main_Entry_fn:
pop rbp
pop rdi
ret
我已经确认问题不在dll中,因为它在调用回调函数的行返回Python,但它在执行回调函数后没有向dll返回值;相反,它再次调用dll。
总而言之,在调用回调函数之后,ctypes会再次调用dll,这不是我想要的。
非常感谢有关如何解决这个问题的想法。
答案 0 :(得分:0)
这个问题的简单答案是返回必须在括号中:return(b)。有了它,它可以正常工作。
但是,现在出现问题时ctypes崩溃了。我在Python ctypes callback crashes on exit with exception code c0000005发布了一个单独的问题。
感谢。