Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers 从ctypes回调返回NASM的指针类型是什么?_Pointers_Nasm_Ctypes - Fatal编程技术网

Pointers 从ctypes回调返回NASM的指针类型是什么?

Pointers 从ctypes回调返回NASM的指针类型是什么?,pointers,nasm,ctypes,Pointers,Nasm,Ctypes,我正在从ctypes调用NASM 64 dll;它包括对SciPy函数integrate.dblquad的回调。回调函数接收指向两个双精度数组的指针,并返回指向两个双精度数组的指针。回调函数在Python中正确执行并显示正确的结果,但我无法将指针返回到NASM 我在5月12日将这个问题作为ctypes问题发布在了。我收到了一个基于C语言的答案,其中有一个在NASM中无法使用的解决方案。我希望有人能帮助我们如何在NASM而不是C中工作 以下是调用dll并执行回调的ctypes代码部分: CA_da

我正在从ctypes调用NASM 64 dll;它包括对SciPy函数integrate.dblquad的回调。回调函数接收指向两个双精度数组的指针,并返回指向两个双精度数组的指针。回调函数在Python中正确执行并显示正确的结果,但我无法将指针返回到NASM


我在5月12日将这个问题作为ctypes问题发布在了。我收到了一个基于C语言的答案,其中有一个在NASM中无法使用的解决方案。我希望有人能帮助我们如何在NASM而不是C中工作

以下是调用dll并执行回调的ctypes代码部分:

CA_data1 = (ctypes.c_double * len(data1))(*data1)
CA_data2 = (ctypes.c_double * len(data2))(*data2)
hDLL = ctypes.WinDLL("C:/NASM_Test_Projects/SciPy_Test/SciPy_Test.dll")
CallName = hDLL.Main_Entry_fn
CallName.argtypes = [ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_longlong)]
CallName.restype = ctypes.c_double

ret_ptr = CallName(CA_data1,CA_data2,length_array_out,lib_call)
mov rdi,callback_data_vals
movsd [rdi],xmm0
movsd [rdi+8],xmm1
mov rcx,callback_data_vals
[make the call to the callback]
以下是回调代码:

from scipy.integrate import dblquad
import ctypes

    def LibraryCall(ptr):
      n = ctypes.cast(ptr,ctypes.POINTER(ctypes.c_double))
      x = n[0]
      y = n[1]
      area = dblquad(lambda x, y: x*y, 0, 0.5, lambda x: 0, lambda x: 1-2*x)
      return_val = area[0], area[1]
      r_val = (ctypes.c_double * len(return_val))(*return_val)
      rv = ctypes.cast(r_val,ctypes.POINTER(ctypes.c_double))
          #All three of these return the same data:
      return (r_val)
      #return (rv)
      #return (return_val)

lib_call = LibraryCB(LibraryCall)
lib_call = ctypes.cast(lib_call,ctypes.POINTER(ctypes.c_longlong))
我也尝试过使用这些声明,但没有区别:

LibraryCB = ctypes.WINFUNCTYPE(None, ctypes.POINTER(ctypes.c_double))

LibraryCB = ctypes.PYFUNCTYPE(None,ctypes.POINTER(ctypes.c_double))
下面是NASM代码的一部分,它调用回调函数并从变量[DBLQUARD_pointer]中的回调函数接收回指针:

我尝试了三个单独的调用来返回指向dll的指针:

    return (r_val)
    return (rv)
    return (return_val)
这三个函数都将相同的错误结果从dll返回给ctypes

在我上一次发布这篇文章时提出的解决方案是将DLL代码更改为使用输入/输出参数,并以C为例,但我知道在NASM中没有等效的方法


总之,我的问题是,如果我有一个来自NASM dll发送和接收指针的回调,我如何处理返回dll的指针

如果我像这里展示的那样去做,马克·托洛宁的上述答案是有效的

在ctypes中:

def LibraryCall(ptr):
    x = ptr[0]
    y = ptr[1]
    area = dblquad(lambda x, y: x*y, 0, 0.5, lambda x: 0, lambda x: 1-2*x)
    ptr[0] = area[0] #new
    ptr[1] = area[1] #new
    return (ptr)
最重要的是,在返回到dll时,我已执行此操作以检查返回值:

mov [dblquad_Pointer],rax
lea rdi,[rel dblquad_Pointer]
mov rbp,qword [rdi] ; Return Pointer
movsd xmm0,qword[rbp]
那是错误的。在进入回调时,我已将值放入本地数组callback\u data\u vals中,并将其传递给回调:

CA_data1 = (ctypes.c_double * len(data1))(*data1)
CA_data2 = (ctypes.c_double * len(data2))(*data2)
hDLL = ctypes.WinDLL("C:/NASM_Test_Projects/SciPy_Test/SciPy_Test.dll")
CallName = hDLL.Main_Entry_fn
CallName.argtypes = [ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_double),ctypes.POINTER(ctypes.c_longlong)]
CallName.restype = ctypes.c_double

ret_ptr = CallName(CA_data1,CA_data2,length_array_out,lib_call)
mov rdi,callback_data_vals
movsd [rdi],xmm0
movsd [rdi+8],xmm1
mov rcx,callback_data_vals
[make the call to the callback]
返回时,返回值位于同一位置(回调\数据\ VAL)。按如下方式访问它们:

mov rdi,callback_data_vals
movsd xmm0,[rdi]
movsd xmm1,[rdi+8]

对于更长的数组,这是不实际的,因为新值必须在Python中的循环中重新分配,这很慢。这里只有两个值,将它们分配给返回指针很简单

“我收到了一个基于C语言的答案,其中有一个在NASM中无法使用的解决方案”。你为什么不能?C编译成汇编。为堆栈上的两个double分配空间,将它们的地址作为参数传递给回调。回调会填充它们…就像另一个答案中的C代码一样。您已经将指针传递给两个double…只需使用该内存返回新值。当前回调的问题是,它正在为局部变量中的返回值分配内存,当函数返回到C时,该内存将被释放。使用传入内存的解决方案似乎适用于任何长度的数组。首先,我需要了解使用传入的指针返回结果的细节。我将尝试ptr=(ctypes.c_double*len(return\u val))(*return\u val)和return(ptr)(传入的指针)。您不必返回任何内容。只需写入传入的指针。请参阅中的Python代码。