如何使用ctypes访问字符指针值?
how to access character pointer value using ctypes?
我编写了一个 DLL,其中我获得了其中一个路径:
//demo.h
__declspec(dllexport) void pathinfo(char * path);
正在代码中执行某些操作以获取此路径。
现在,我编写的用于从 DLL 检索此路径的 python 脚本如下所示:
//demo.py
import sys
import ctypes
from ctypes import *
class demo(object):
def __init__(self):
self.demoDLL=CDLL("demo.dll")
def pathinfo(self):
path=c_char()
self.demoDLL.pathinfo.argtypes(POINTER(c_char))
self.demoDLL.pathinfo.result=None
self.demoDLL.pathinfo(byref(path))
return path.value
if __name__=='__main__':
abc=demo()
path_info=abc.pathinfo()
print "information of the path:",path_info
但我能看到的值只是路径的第一个字符,而不是整个字符串。
谁能帮我解决这个问题?
还没有做过,但是做了以下:
要传递 ints
的数组,例如,使用这个:
创建一个类型,比如 20 个整数:
Ints20 = c_int * 20
创建实例:
data = Ints20()
然后就可以通过data
了。
使用 list
函数从 data
中提取数字:
values = list(data)
所以也许你可以对字符做同样的事情:
Chars20 = c_char * 20
path = Chars20()
然后:
self.demoDLL.pathinfo(path)
在 c_char 数组的情况下,不需要使用 list
函数,但是这个有效:
return path.value
您只看到第一个字符的原因是,通过调用 c_char()
,您创建了一个 char
值,Python 将其视为 str
(Python 2) 对象或 bytes
(Python 3) 长度为 1 的对象。您可能很幸运没有遇到分段错误。通过在 C 代码中写入超过 1 个字节或长度 > 0 的以 NULL 结尾的字符串(例如使用 strcpy
),您实际上会产生未检测到的缓冲区溢出。 ctypes
不知道你在指针的内存位置写入了多少字节。 path.value
仍然是长度为 1 的 str
/ bytes
。
最好将 C pathinfo
函数改成类似
的东西
size_t pathinfo(char* path, size_t bsize);
使用 ctypes.create_string_buffer()
在您的 Python 代码中分配内存,并让 pathinfo
return 成为结果的长度。当然,您必须在 C 代码中使用 bsize
检查 char* path
是否足够大。
Python-代码如下所示:
buf = ctypes.create_string_buffer(256)
result_len = pathinfo(buf, len(buf))
if result_len == len(buf):
# buffer may have been too short,
# try again with larger buffer
...
restlt_str = buf[0:result_len].decode('utf-8') # or another encoding
还要注意 C 域中的 NULL 终止符、将 python 字符串转换为 char*
和返回时的字符编码、关于 str
/ bytes
的更改在 ctypes
关于 Python 2 和 Python 3.
我编写了一个 DLL,其中我获得了其中一个路径:
//demo.h
__declspec(dllexport) void pathinfo(char * path);
正在代码中执行某些操作以获取此路径。 现在,我编写的用于从 DLL 检索此路径的 python 脚本如下所示:
//demo.py
import sys
import ctypes
from ctypes import *
class demo(object):
def __init__(self):
self.demoDLL=CDLL("demo.dll")
def pathinfo(self):
path=c_char()
self.demoDLL.pathinfo.argtypes(POINTER(c_char))
self.demoDLL.pathinfo.result=None
self.demoDLL.pathinfo(byref(path))
return path.value
if __name__=='__main__':
abc=demo()
path_info=abc.pathinfo()
print "information of the path:",path_info
但我能看到的值只是路径的第一个字符,而不是整个字符串。
谁能帮我解决这个问题?
还没有做过,但是做了以下:
要传递 ints
的数组,例如,使用这个:
创建一个类型,比如 20 个整数:
Ints20 = c_int * 20
创建实例:
data = Ints20()
然后就可以通过data
了。
使用 list
函数从 data
中提取数字:
values = list(data)
所以也许你可以对字符做同样的事情:
Chars20 = c_char * 20
path = Chars20()
然后:
self.demoDLL.pathinfo(path)
在 c_char 数组的情况下,不需要使用 list
函数,但是这个有效:
return path.value
您只看到第一个字符的原因是,通过调用 c_char()
,您创建了一个 char
值,Python 将其视为 str
(Python 2) 对象或 bytes
(Python 3) 长度为 1 的对象。您可能很幸运没有遇到分段错误。通过在 C 代码中写入超过 1 个字节或长度 > 0 的以 NULL 结尾的字符串(例如使用 strcpy
),您实际上会产生未检测到的缓冲区溢出。 ctypes
不知道你在指针的内存位置写入了多少字节。 path.value
仍然是长度为 1 的 str
/ bytes
。
最好将 C pathinfo
函数改成类似
size_t pathinfo(char* path, size_t bsize);
使用 ctypes.create_string_buffer()
在您的 Python 代码中分配内存,并让 pathinfo
return 成为结果的长度。当然,您必须在 C 代码中使用 bsize
检查 char* path
是否足够大。
Python-代码如下所示:
buf = ctypes.create_string_buffer(256)
result_len = pathinfo(buf, len(buf))
if result_len == len(buf):
# buffer may have been too short,
# try again with larger buffer
...
restlt_str = buf[0:result_len].decode('utf-8') # or another encoding
还要注意 C 域中的 NULL 终止符、将 python 字符串转换为 char*
和返回时的字符编码、关于 str
/ bytes
的更改在 ctypes
关于 Python 2 和 Python 3.