Ctypes执行回调函数,然后再次错误地调用dll

2024-05-12 19:57:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我在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”的行跳到标记为“CALLBACK FUNCTION IN PYTHON”的行。它正确地执行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,这不是我想要的。你知道吗

非常感谢你提出解决这个问题的建议。你知道吗


Tags: 函数callctypeslengthraxfndlldouble