python3 ctypes该怎么实现乐易模块里的一些功能?

e 内存_申请内存(pid,(int)) 内存_申请文本内存 (pid, “xxx”) 进程_取函数入口 (pid, “xxx.dll”, “xxx”)e

【相关推荐】



  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/1013913
  • 你也可以参考下这篇文章:python——Windows API和ctypes模块和实现键盘记录
  • 除此之外, 这篇博客: Python ctypes模块的基本使用中的 3、测试代码 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:

    (C/C++ 代码在 Windows VS 环境编写)

    // 下列 ifdef 块是创建使从 DLL 导出更简单的宏的标准方法。
    // 在预处理器中定义了 MYDLL_EXPORTS 符号,而调用方不包含此符号。
    // 源文件中包含此文件的任何其他项目都会将 MYDLL_API 视为是从 DLL 导入的,
    // 而此 DLL 则将用此宏定义的符号视为是被导出的。
    #ifdef MYDLL_EXPORTS
    #define MYDLL_API __declspec(dllexport)
    #else
    #define MYDLL_API __declspec(dllimport)
    #endif
    
    //ctypes需要提供c接口,主要是目前cpp还没有统一的abi
    extern "C"
    {
    	//导出一个全局变量
    	extern MYDLL_API int my_number;
    	//函数
    	MYDLL_API int my_func(int a, int b);
    	MYDLL_API double my_func2(double a, double b);
    	MYDLL_API int * my_func3(char *a, double *b, const char *str);
    	//指针
    	extern MYDLL_API char *char_ptr;
    	extern MYDLL_API int *int_ptr;
    	extern MYDLL_API int *null_ptr;
    	//打印dll中的变量
    	MYDLL_API void print_var();
    	//结构体
    	struct MYDLL_API MyStruct
    	{
    		int a;
    		double b;
    	};
    	MYDLL_API MyStruct my_func4(const MyStruct &arg);
    	MYDLL_API MyStruct * my_func5(MyStruct *arg);
    }
    
    // MSVC模板默认带pch,设置为不使用预编译头
    // #include "pch.h"
    #include "mydll.h"
    #include <iostream>
    
    MYDLL_API int my_number = 1992;
    
    MYDLL_API int my_func(int a, int b)
    {
    	return a + b;
    }
    
    MYDLL_API double my_func2(double a, double b)
    {
    	return a + b;
    }
    
    MYDLL_API int * my_func3(char * a, double * b, const char *str)
    {
    	std::cout << "dll myfunc3:" << str << std::endl;
    	my_number = *a + int(*b);
    	return &my_number;
    }
    
    MYDLL_API char *char_ptr = new char(65);
    MYDLL_API int *int_ptr = new int(250);
    MYDLL_API int *null_ptr = nullptr;
    
    MYDLL_API void print_var()
    {
    	std::cout << "dll print var:"
    		<< "\n\tmy number:" << my_number
    		<< "\n\tchar ptr:" << *char_ptr
    		<< "\n\tint ptr:" << *int_ptr << std::endl;
    }
    
    MYDLL_API MyStruct my_func4(const MyStruct & arg)
    {
    	MyStruct ret{ 12,34.5 };
    	std::cout << "dll myfunc4:"
    		<< "in:" << arg.a << " " << arg.b
    		<< "ret:" << ret.a << " " << ret.b << std::endl;
    	return ret;
    }
    
    MYDLL_API MyStruct * my_func5(MyStruct * arg)
    {
    	if (arg) {
    		arg->a = 67;
    		arg->b = 89.5;
    	}
    	return arg;
    }
    
    import ctypes
    
    #dll = ctypes.cdll.LoadLibrary("msvcrt.dll")
    #dll.printf(b"hello ctypes\n")
    
    dll = ctypes.cdll.LoadLibrary(
        "D:/TestSpace/TestCpp_20210617_mydll/x64/Release/mydll.dll")
    #访问变量
    print(dll.my_number)  # 打印<_FuncPtr object at 0x0000022537F1B450>,默认应该是当作函数访问的
    print(ctypes.c_int.in_dll(dll, 'my_number').value)
    #访问函数
    print(dll.my_func)
    print(dll.my_func(12, 34))
    #ctypes 默认假定函数返回 int 类型,可以设置函数对象的 restype 属性来指定具体类型。
    #对于参数类型也可以通过设置函数对象的 argtypes 来指定具体类型,防止不合理的参数传递。
    my_func2 = dll.my_func2
    my_func2.argtypes = [ctypes.c_double, ctypes.c_double]
    my_func2.restype = ctypes.c_double
    print(my_func2(12, 34.5))
    my_func3 = dll.my_func3
    my_func3.argtypes = [ctypes.c_char_p, ctypes.POINTER(ctypes.c_double)]
    my_func3.restype = ctypes.POINTER(ctypes.c_int)
    arg1 = ctypes.c_char(12)
    arg2 = ctypes.c_double(1000)
    #byref相当于取引用,c字符串传字节数组
    ret = my_func3(ctypes.byref(arg1), ctypes.byref(arg2), b'hello ctypes.')
    print(ret.contents.value)
    
    dll.print_var()
    #指针变量
    #ptr = ctypes.POINTER(ctypes.c_int)
    # char(65)->print(b'A'),可能会把后面挨着的字节内容也打印
    print(ctypes.c_char_p.in_dll(dll, 'char_ptr').value)
    print(ctypes.POINTER(ctypes.c_int).in_dll(dll, 'int_ptr').contents.value)
    ctypes.POINTER(ctypes.c_int).in_dll(dll, 'int_ptr').contents.value = 520
    #空指针bool值为false
    print(bool(ctypes.POINTER(ctypes.c_int).in_dll(dll, 'null_ptr')))
    dll.print_var()
    
    #struct或union必须派生ctypes给的基类Structure和Union
    #每个子类都必须定义一个_fields_属性,_fields_必须是一个2-tuples列表,包含一个字段名和一个字段类型。
    
    
    class MyStruct(ctypes.Structure):
        _fields_ = [
            ("a", ctypes.c_int),
            ("b", ctypes.c_double)
        ]
    
    
    my_func4 = dll.my_func4
    my_func4.restype = MyStruct
    arg = MyStruct()
    arg.a = 10
    arg.b = 11
    #print(ctypes.sizeof(MyStruct))
    ret = my_func4(arg)
    print('my_func4 ret:', ret.a, '  ', ret.b)
    my_func5 = dll.my_func5
    my_func5.restype = ctypes.POINTER(MyStruct)
    ret = my_func5(ctypes.byref(arg)).contents
    print('my_func5 ret:', ret.a, '  ', ret.b)
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^