使用 ctypes 从函数返回字符串C++会给出大的 int,而不是 char 指针

Returning string from C++ function with ctypes gives large int, not char pointer

本文关键字:int 指针 char 函数 ctypes 返回 字符串 C++ 使用      更新时间:2023-10-16

我正在尝试使用python中的ctypes从dll调用C++函数。我目前的问题是该函数似乎返回一个大的整数,无论是正数还是负数,而不是我期望的字符指针。如果我将该 int 转换为 c_char_p 并在其上调用 .value,它每次都会杀死我的内核。我已经查看了整个网站和文档,但无法弄清楚这一点。我在这个网站上看到的很多东西甚至会给我抛出错误,比如将字符串传递给 ctypes opjects 和函数,而它们应该是字节对象或类似的东西。下面是我变成 dll 的 c++ 代码和我用来从 dll 调用函数的 python 代码。如果有人可以帮助我,那就太棒了。说某事是有问题的函数。谢谢。

TestLibrary.h

#pragma once
#ifdef TESTLIBRARY_EXPORTS
#define TESTLIBRARY_API __declspec(dllexport)
#else
#define TESTLIBRARY_API __declspec(dllexport)
#endif
#include <windows.h>
#include <cstring>
#ifdef __cplusplus
extern "C"
{
#endif
TESTLIBRARY_API char* SaySomething(const char* phrase);
#ifdef __cplusplus
};
#endif

测试库.cpp

#include "stdafx.h"
#include "TestLibrary.h"
#include <iostream>
TESTLIBRARY_API char* SaySomething(const char* phrase)
{
char* p = new char [100];
p = "string something";
return p;
}

tester2.py

import ctypes
dbl = ctypes.c_double
pChar = ctypes.c_char_p
pVoid = ctypes.c_void_p
libName = (r"D:DocumentsCoding StuffVisual Studio 2017ProjectsTestLibrary"
r"Solutionx64DebugTestLibrary.dll")
x = ctypes.windll.LoadLibrary(libName)
x.SaySomething.argtypes = [pChar]
x.SaySomething.restypes = pChar
phrase = b"Hi"
phrase = pChar(phrase)
res = x.SaySomething(phrase)

虽然你可以创建一个 API 来执行你正在尝试做的事情,但你目前会遇到内存泄漏。 更好的解决方案是让 Python 为结果分配和管理内存。

我还修复了注释中提到的dllimport,并在.cpp文件中定义了TESTLIBRARY_EXPORTS,以便该函数将从 DLL 导出。restype也被修复了。

TesterLibrary.h

#pragma once
#ifdef TESTLIBRARY_EXPORTS
#define TESTLIBRARY_API __declspec(dllexport)
#else
#define TESTLIBRARY_API __declspec(dllimport)
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
TESTLIBRARY_API char* SaySomething(const char* phrase, char* result, size_t resultMaxLength);
#ifdef __cplusplus
}
#endif

测试器库.cpp

#define TESTLIBRARY_EXPORTS
#include "TestLibrary.h"
#include <stdio.h>
TESTLIBRARY_API char* SaySomething(const char* phrase, char* result, size_t resultMaxLength)
{
_snprintf_s(result,resultMaxLength,_TRUNCATE,"Decorated <%s>",phrase);
return result;
}

tester2.py

import ctypes
libName = (r"TestLibrary.dll")
x = ctypes.CDLL(libName)
x.SaySomething.argtypes = [ctypes.c_char_p,ctypes.c_char_p,ctypes.c_size_t]
x.SaySomething.restype = ctypes.c_char_p
phrase = b"Hi"
result = ctypes.create_string_buffer(100)
res = x.SaySomething(phrase,result,ctypes.sizeof(result))
print(res)
print(result.value)

输出

b'Decorated <Hi>'
b'Decorated <Hi>'

Python 将在没有更多引用时自动释放result缓冲区。