pythonhavenoname 2023-08-31 19:31 采纳率: 0%
浏览 3

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

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

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-08-31 22:50
    关注

    【相关推荐】



    • 这有个类似的问题, 你可以参考下: 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)
      

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

报告相同问题?

问题事件

  • 创建了问题 8月31日