如何使用 CTypes 将 wchar_t** - 以空结尾的 UNICODE 字符串数组 - 返回到 Python 脚
How can I return a wchar_t** - null terminated array of UNICODE strings - to a Python script using CTypes
给定在名为c-lib.so
的共享库中实现的两个函数,如何使用CTypes正确定义/包装函数。
set_list_of_strings(wchar_t** list);
wchar_t** get_list_of_strings();
对于 set 函数,如果添加到 python 包装器模块中,则以下内容有效
import ctypes
_lib = ctypes.CDLL('c-lib.so')
def set_list_of_strings(list):
global _dsl
arr = (ctypes.c_wchar_p * len(list))
arr[:] = list
_lib.set_list_of_strings(arr)
我有两个与上述相关的问题。
- 我将如何定义'set_list_of_strings.argtypes[??]来检查/限制输入。
- 我将如何定义包装函数以正确返回字符串列表。
谢谢
我做了一个简单的例子,其中 C(实际上是包装的 C++(代码获取字符串列表并复制它们,然后 get_list_of_strings
函数返回它们以字符串位置为后缀。
至于 python 中函数的定义:
# wchar_t** get_list_of_strings()
get_list_of_strings.restype = ctypes.POINTER(ctypes.c_wchar_p)
# void set_list_of_strings(wchar_t** list)
set_list_of_strings.argtypes = (ctypes.POINTER(ctypes.c_wchar_p), )
从wchar_t**
中获取字符串的方法非常简单:您可以索引返回的指针本身并从中获取字符串。由于返回的数组以 nullptr
结尾(转换为 None
(,您可以在此时停止迭代:
result = get_list_of_strings()
index = 0
while True:
p = result[index]
if p is None:
break
index += 1
print(p)
棘手的部分是初始化wchar_t*
指针数组:
def list_to_wchar_t_pp(l):
if not l:
return None
buffers = [ctypes.create_unicode_buffer(s) for s in l]
addresses = list(map(ctypes.addressof, buffers))
addresses.append(0) # append nullptr at the end
pp = (ctypes.c_wchar_p * (len(l) + 1))(*addresses)
return pp
我们从字符串创建 Unicode 缓冲区,获取这些缓冲区的地址,在末尾添加一个空指针。然后我们使用这些地址初始化指针数组。
蟒蛇代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import string
import ctypes
def list_to_wchar_t_pp(l):
if not l:
return None
buffers = [ctypes.create_unicode_buffer(s) for s in l]
addresses = list(map(ctypes.addressof, buffers))
addresses.append(0) # append nullptr at the end
pp = (ctypes.c_wchar_p * (len(l) + 1))(*addresses)
return pp
def main():
dll = ctypes.WinDLL(r"TestDll.dll")
# wchar_t** get_list_of_strings()
get_list_of_strings = dll.get_list_of_strings
get_list_of_strings.restype = ctypes.POINTER(ctypes.c_wchar_p)
# void set_list_of_strings(wchar_t** list)
set_list_of_strings = dll.set_list_of_strings
set_list_of_strings.argtypes = (ctypes.POINTER(ctypes.c_wchar_p), )
strings = ["foo", "bar", "baz"]
pp_strings = list_to_wchar_t_pp(strings)
if not pp_strings:
return -1
set_list_of_strings(pp_strings)
result = get_list_of_strings()
index = 0
while True:
p = result[index]
if p is None:
break
index += 1
print(p)
return 0
if __name__ == "__main__":
sys.exit(main())
输出:
foo #1
bar #2
baz #3
C++共享库(Windows DLL(的代码;请注意,释放全局缓冲区及其指针也应实现。
#include <cstdlib>
#include <string>
#include <iostream>
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
static wchar_t** g_list;
EXTERN_DLL_EXPORT void set_list_of_strings(wchar_t** list)
{
auto count = 0;
while(true)
{
const auto p = list[count];
if (p == nullptr)
break;
count++;
}
if (count == 0)
return;
g_list = new wchar_t* [count + 1];
for(int i = 0; i < count; i++)
{
const auto s = list[i];
const auto len = wcslen(s);
auto p = new wchar_t[len + 1];
wcscpy_s(p, len + 1, s);
g_list[i] = p;
}
g_list[count] = nullptr;
}
EXTERN_DLL_EXPORT wchar_t** get_list_of_strings()
{
if (g_list == nullptr)
return nullptr;
auto count = 0;
while(true) {
const auto p = g_list[count];
if (p == nullptr)
break;
count++;
}
if (count == 0)
return nullptr;
const auto new_list = new wchar_t* [count + 1];
for(int i = 0; i < count; i++)
{
std::wstring ws(g_list[i]);
ws += L" #" + std::to_wstring(i + 1);
const auto length = ws.length();
const auto buff_len = ws.length() + 1;
const auto buff = new wchar_t[buff_len];
wcscpy_s(buff, ws.length() + 1, ws.data());
new_list[i] = buff;
}
new_list[count] = nullptr;
return new_list;
}
相关文章:
- 如何将unicode字符串从C++传递到delphi
- 将 unicode 字符串与 c ++ 符号进行比较?
- C++:Unicode 字符串文字的可移植性
- 如何使用 CTypes 将 wchar_t** - 以空结尾的 UNICODE 字符串数组 - 返回到 Python 脚
- Xamarin Android:在 C++ 中将字符串从 C# 封送到 Unicode 字符串的正确方法是什么?
- 如何在 python 包装中使用 unicode 字符串用于带有 cython 的 c++ 类?
- 如何使用poco :: logger记录Unicode字符串
- 如何将 Unicode 字符串连接成字符串以传递到 mysql 调用中
- Unicode字符串Visual C 构造函数
- 如何将 (ICU4C) Unicode 字符串逐个字符复制到另一个 Unicode 字符串
- 如何从Windows中的进程中读取Unicode字符串
- 如何在Visual C 中的BSTR和32位Unicode字符串之间进行转换
- C 编译器如何从UTF8源文件中生成Unicode字符串文字
- 如何检测终端中的unicode字符串宽度
- 如何在字符级别操作Unicode字符串
- 获取Crypto++中Unicode字符串的SHA1
- 将 unicode 字符串转换为字符串
- c++Unicode字符串与易混淆字符的比较.例如(U 0054)应为==(U03A4)等
- 如何在带L(或不带L)的变量中传递unicode字符串
- C++中的Unicode字符串处理