python在类中的dll回调函数中访问self

标签 python ctypes

我有一些像这样的 api 的 dll 函数:

def dllcallback(items):
  pass

我想在与 dll 回调链接的类函数中访问 self。

class myobject(object):
  def __init__(self):
    self.a = 999
  @dllcallback
  def mycallback(self, items):
    print (self.a)
    self.a = 888
    print (self.a)

我不认为 dllcallback 接受 self 作为参数。所以这是失败的。 我希望 myobject.mycallback 在 api 调用 dllcallback 时触发,并显示:

999
888

我尝试了下面的方法使内部函数可以访问“self”,但是这种方法杀死了内核...

class myobject(object):
  def __init__(self):
    self.a = 999
  def callbacks(self):
    @dllcallback
    def mycallback(items):
      print (self.a)
      self.a = 888
      print (self.a)

我不确定内核死机的原因。提前感谢您的任何建议。

更新:20180912 1436

实际上,override 方法可以在没有 self 作为参数的情况下被调用,

class myobject(object):
  def __init__(self):
    self.a = 999
  @dllcallback
  def mycallback(items):
    global self
    print (self.a)
    self.a = 888
    print (self.a)

NameError: name 'self' is not defined

我想“self”不能像这样获得...有什么建议吗?

更新:20180913 1645

在编写包含 ctypes dll 回调函数的类方面取得了一些进展

class myobject(object):
  def __init__(self):
    if u'32bit' in architecture(): # 32bit WinOS
      self.spdll = windll.LoadLibrary('XXX.dll')
    else:                          # 64bit WinOS
      self.spdll = cdll.LoadLibrary('XXX.dll')
    self.a = 999

  def callbacksinit(self):
    def mycallback(items):
      print (self.a)
      self.a = 888
      print (self.a)
    self.mycallbackaddr = WINFUNCTYPE(None, c_char_p) 

  def regcallbacks(self):
    self.spdll.APICALLBACK(self.mycallbackaddr)

通过这段代码,我可以在 API 触发 mycallback 时访问 self.a。 对我来说幸运的是,mycallback 完成后 self.a 可以更改为 888,而无需在 mycallback 中进行全局声明(例如全局 self)。 我不知道为什么会这样......为什么 WINFUNCTYPE(None, c_char_p) 以这种方式工作以及为什么 self.a 可以在没有全局声明的情况下更改。我暂时搁置这个问题,也许有人可以消除我的疑虑。

最佳答案

您的更新是一个有效的解决方案。您可以更新 self 因为它是可变的。您不需要 global(或在本例中为 nonlocal)声明来访问它。您只需要那些重新分配变量。

例如:

def func():
    L = []

    def inner():
        #nonlocal L  # Uncomment to work
        L = [1,2,3]  # Reassign L

    inner()          # Call the function and attempt to modify L
    return L

def func2():
    L = []

    def inner():
        L[:] = [1,2,3] # Mutate L

    inner()            # Call the function and attempt to modify L
    return L

print(func())
print(func2())

输出:

[]
[1, 2, 3]

这是您的方法的完整示例...

测试.c

#include <wchar.h>
#define API __declspec(dllexport)

typedef void (*CALLBACK)(const wchar_t*);

API void do_callback(CALLBACK cb)
{
    cb(L"one");
    cb(L"two");
    cb(L"three");
}

测试.py

from ctypes import *

CALLBACK = CFUNCTYPE(None,c_wchar_p)

class Test:
    dll = CDLL('test')
    dll.do_callback.argtypes = CALLBACK,
    dll.do_callback.restype = None

    def __init__(self):
        self.count = 0

    def get_callback(self):

        @CALLBACK
        def callback(s):
            self.count += 1     # nonlocal, but mutable
            print(self.count,s)

        return callback

    def do(self):
        self.dll.do_callback(self.get_callback())

t = Test()
t.do()

输出:

1 one
2 two
3 three

关于python在类中的dll回调函数中访问self,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52288408/

相关文章:

Python:是否可以有一个列表列表?以及如何调用特定列表?

python - 如何正确地将 tflite_graph.pb 转换为 detect.tflite

python - 在 python ctypes 中控制内存对齐

python - pythonapi.PyObject_GC_UnTrack 返回什么?

python - 使用 Python 将 CSV 文件中的 GMT 转换为 EST

c# - 从 C# 运行多个 python 脚本

python - Matplotlib png 输出在 reportlab 的 pdf 中出现 "broken"

python - 用 Python 打包和用 C 解包

c++ - 从 python 运行 C++ 代码

python - 如何使用 ctypes 读取具有自定义结构的 dll 的输出?