gpt4 book ai didi

python - argv 的 ctypes 错误

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:01:44 25 4
gpt4 key购买 nike

我正在尝试从带有类型的 python 调用我的 C++ 库,但我无法作为 IP 参数和 HEX 代码传递,任何人都可以帮助我吗?

import sys 
import ctypes

lib = ctypes.CDLL('./hello.so')

LP_c_char = ctypes.POINTER(ctypes.c_char)
LP_LP_c_char = ctypes.POINTER(LP_c_char)

lib.connect_pe_func.argtypes = (ctypes.c_int, LP_LP_c_char)

argc = 2
argv = ["192.168.2.170","2600000026"]
for i, arg in enumerate(sys.argv):
enc_arg = arg.encode('utf-8')
argv[i] = ctypes.create_string_buffer(enc_arg)

lib.connect_pe_func(argc, argv)

这是错误消息,如何将 IP 和十六进制代码插入 argv vector 而不会出现此错误?

---------------------------------------------------------------------------
ArgumentError Traceback (most recent call last)
<ipython-input-21-f59eabe02690> in <module>
17 argv[i] = ctypes.create_string_buffer(enc_arg)
18
---> 19 lib.connect_pe_func(argc, argv)

ArgumentError: argument 2: <class 'TypeError'>: expected LP_LP_c_char instance instead of list

为了完整起见,我还插入了我编译并制作成hello.so库的C++代码

#include <stdio.h>
#include <errno.h>
#include <string>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
#include <iostream>
#include <unistd.h>
#include <sstream>
#include "connect_PE_func.h"
using namespace std;


extern "C" char * connect_pe_func(int argc, char *argv[])
{
int sockfd, n;
int connected = 0;
struct sockaddr_in servaddr;
std::string serveraddr = argv[1];

sockfd = socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(serveraddr.c_str());
servaddr.sin_port = htons(9761);

connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

std::string pref_hex;
std::string hex("0x");
std::string test = argv[2];
size_t numbytes = test.size() / 2;

uint8_t command[numbytes];

for (size_t w = 0, x = 0; w < numbytes; ++w, x += 2)
{
pref_hex = hex + test.substr(x, 2);
cout << pref_hex;
command[w] = stoi(pref_hex, nullptr, 16);
}

int bytes_to_send = sizeof(command);

send(sockfd, command, bytes_to_send, 0);
uint8_t output_command[numbytes];
recv(sockfd, output_command, bytes_to_send, 0);

char test_out[10];

for (size_t w = 0, x = 0; w < numbytes; ++w, x += 2)
{
test_out[x] = (char)output_command[w];
}
return test_out;
};

extern "C" char * hello_world(char * name){
char * output = (char *) calloc(sizeof(name)+7, sizeof(char));
strcat(output, "Hello ");
strcat(output, name);
strcat(output, "\0");
//output[sizeof(output)-1] = '/0';
return output;

};

最佳答案

Python 列表不能作为指针的指针传递。

要从 Python 创建和填充指针的指针,您需要:

  • 创建一个指针数组:p = (LP_c_char*len(argv))()(为指针分配空间)
  • 将其转换为指针的指针:na = ctypes.cast(p, LP_LP_c_char)(使其与指针形式的衰减指针兼容)<

或者没有重新定义:

p = (ctypes.POINTER(ctypes.c_char)*len(argv))()
na = ctypes.cast(p, ctypes.POINTER(ctypes.POINTER(ctypes.c_char)))

固定代码:

import sys
import ctypes

lib = ctypes.CDLL('./hello.so')

LP_c_char = ctypes.POINTER(ctypes.c_char)
LP_LP_c_char = ctypes.POINTER(LP_c_char)

lib.connect_pe_func.argtypes = (ctypes.c_int, LP_LP_c_char)

argv = ["192.168.2.170","2600000026"]
argc = len(argv)

p = (LP_c_char*len(argv))()
for i, arg in enumerate(argv): # not sys.argv, but argv!!!
enc_arg = arg.encode('utf-8')
p[i] = ctypes.create_string_buffer(enc_arg)

na = ctypes.cast(p, LP_LP_c_char)

lib.connect_pe_func(argc, na)

为了测试这个,我创建了一个非常简单的 C++ 代码(而不是你的)

#include <stdio.h>

extern "C" char * connect_pe_func(int argc, char *argv[])
{
for (int i=0;i<argc;i++)
{
puts(argv[i]);
}
return 0;
}

内置:g++ -shared -o hello.so test.cpp

运行 python 模块证明参数传递正确:

192.168.2.170
2600000026

灵感来自 Pointers and arrays in Python ctypes

关于python - argv 的 ctypes 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58598012/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com