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

时间:2018-04-16 15:12:56

标签: python dll callback nasm ctypes

我在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,这不是我想要的。

非常感谢有关如何解决这个问题的想法。

1 个答案:

答案 0 :(得分:0)

这个问题的简单答案是返回必须在括号中:return(b)。有了它,它可以正常工作。

但是,现在出现问题时ctypes崩溃了。我在Python ctypes callback crashes on exit with exception code c0000005发布了一个单独的问题。

感谢。