I have a DLL library in C, I managed to initialize the functions in python a receive and send data to it. Now I'm trying to reorganize the python code to have all my DLL python functions in one big class.
This is what I have in Visual Studio.
This is 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);
this is 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;
}
this is my original python code without the 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)
and this is my python test code trying to implement the class that will contain all my dll function inits. I'm just testing with function_1 and function_2 for now. I will add other functions in the future.
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)
The error I get is
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'
I would appreciate any suggestions. Thanks.
CodePudding user response:
It is because you define the class's init to have py_function_1
and py_function_2
as the constructors. Thus, you should pass the test.function_1
and test.function_2
when initializing the object, i.e.
myapi = my_outer_class(test.function_1, test.function_2)
and then use it correctly in class' init
, i.e.
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
The solution above means that the user has the ability to supply other callable in the constructor.
Another alternative is to restrict the user to use only the one from .dll
. A possible solution would be the one mentioned in the comments section. However, I don't think this is the best practice because it uses the global scope to find the function. This will be an issue when you tried to scale your script, say, by separating the class in another file. You will need to include non-class code there.
Better solution if you want restrict the user to not altering the function_1
and function_2
is to load the .dll
in the class' init
instead of in the global scope.
class my_outer_class:
def __init__(self):
test = ctypes.WinDLL('Project.dll')
self.py_function_1 = test.function_1