Python error TypeError: __init__() missing 2 required positional arguments: and ctypes

Python error TypeError: __init__() missing 2 required positional arguments: and ctypes

我有一个 C 语言的 DLL 库,我设法初始化了 python 中的函数,并向它接收和发送数据。现在我正在尝试重新组织 python 代码,以便将我所有的 DLL python 函数都放在一个大的 class.

这就是我在 Visual Studio 中的内容。

这是Hello.h

#pragma once
#include<stdio.h>
#include<stdint.h>

#ifdef SOME_API_EXPORTS
#define SOME_API __declspec(dllexport)
#else
#define SOME_API __declspec(dllimport)
#endif

SOME_API int sum(int a, int b);

SOME_API int mul(int a, int b);

SOME_API void message(void);

#define max_length 63U

typedef struct
{
    uint8_t param1;

    uint32_t param2;

    uint8_t param3;

    uint8_t param4[max_length];

} struct_1;

SOME_API void message_2(struct_1* request);

SOME_API int function_1(uint8_t param_1, uint8_t param_2);
SOME_API int function_2(uint8_t param_1, uint8_t param_2);

这是Hello.C

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include "Hello.h"
#include <inttypes.h>

 
int sum(int a, int b) {
        return a + b;
    }

int mul(int a, int b) {
    return a * b;
}

void message(void)
{
    puts("hello from dll\n");
}

SOME_API void message_2(struct_1* request)
{
    printf("data: request=[%d %d %d %s]\n", 
    request->param1, request->param2, request->param3, request->param4);
    //do some processing

}

SOME_API int function_1(uint8_t param_1, uint8_t param_2)
{
    int status;
    //do some processing
    printf("%u  , %u  \n", param_1, param_2);
    status = 1;
    return status;
}

SOME_API int function_2(uint8_t param_1, uint8_t param_2)
{
    int status;
    //do some processing
    printf("%u  , %u  \n", param_1, param_2);
    status = 0;
    return status;
}

这是我的原始 python 代码,没有 class。

import ctypes

test = ctypes.WinDLL('Project.dll')

max_length = 63

class struct_1(ctypes.Structure):
    _fields_ = [("param1", ctypes.c_ubyte),
                ("param2", ctypes.c_uint32),
                ("param3", ctypes.c_ubyte),
                ("param4", ctypes.c_char * max_length)]

test.message()

##req = struct_1(1, 2 , 3,"test".encode('utf-8'))
##result = test.message_2(ctypes.byref(req))

py_function_1 = test.function_1
py_function_1.argtype = (ctypes.c_uint8,ctypes.c_uint8 )
py_function_1.restype = ctypes.c_int
py_function_1(255,255)

return_val = py_function_1()
print(return_val)

py_function_2 = test.function_2
py_function_2.argtype = (ctypes.c_uint8,ctypes.c_uint8 )
py_function_2.restype = ctypes.c_int
py_function_2(255,255)

return_val = py_function_2()

print(return_val)

这是我的 python 测试代码,它试图实现 class,它将包含我所有的 dll 函数初始化。我现在只是用 function_1 和 function_2 进行测试。以后我会添加其他功能。

import ctypes

test = ctypes.WinDLL('Project.dll')

max_length = 63

class struct_1(ctypes.Structure):
    _fields_ = [("param1", ctypes.c_ubyte),
                ("param2", ctypes.c_uint32),
                ("param3", ctypes.c_ubyte),
                ("param4", ctypes.c_char * max_length)]

class my_outer_class:

    def __init__(self,py_function_1,py_function_2):

        self.py_function_1 = test.function_1
        self.py_function_1.argtype = (ctypes.c_uint8,ctypes.c_uint8 )
        self.py_function_1.restype = ctypes.c_int

        self.py_function_2 = test.function_2
        self.py_function_2.argtype = (ctypes.c_uint8,ctypes.c_uint8 )
        self.py_function_2.restype = ctypes.c_int

myapi = my_outer_class()
            
result = myapi.py_function_1(255,255)
print(result)

result = myapi.py_function_2(255,255)
print(result)

我得到的错误是

Traceback (most recent call last):
  File "C:\Users\Dude\OneDrive\Desktop\Test.py", line 25, in <module>
    myapi = my_outer_class()
TypeError: __init__() missing 2 required positional arguments: 'py_function_1' and 'py_function_2'

如果有任何建议,我将不胜感激。谢谢。

因为你定义了class的init函数,让py_function_1py_function_2作为构造函数。因此,您应该在初始化对象时传递 test.function_1test.function_2,即

myapi = my_outer_class(test.function_1, test.function_2)

然后在class'init中正确使用,即

class my_outer_class:

    def __init__(self, py_function_1, py_function_2):

        self.py_function_1 = py_function_1 # change this to use the constructor
        ... # other lines

        self.py_function_2 = py_function_2 # change this to use the constructor
        ... # other lines

上述解决方案意味着用户可以在构造函数中提供其他可调用对象。

另一种选择是限制用户使用来自.dll的那个。一种可能的解决方案是评论部分中提到的解决方案。但是,我认为这不是最佳实践,因为它使用全局范围来查找函数。当您尝试缩放脚本时,例如通过将 class 分隔到另一个文件中,这将是一个问题。您需要在此处包含非 class 代码。

如果您想限制用户不更改 function_1function_2,更好的解决方案是在 class 中加载 .dll' init而不是在全球范围内。

class my_outer_class:

    def __init__(self):
        test = ctypes.WinDLL('Project.dll')
        self.py_function_1 = test.function_1