【发布时间】:2021-08-04 21:17:29
【问题描述】:
我正在开发一个调用 C++ 开发的 DLL 的 Python 3 应用程序。 DLL 读取数据库记录并将记录缓冲区返回给 Python 应用程序。我遇到的问题是数据库记录可能包含 x'00'(空)字符。发生这种情况时,返回给 Python 应用程序的记录缓冲区在空字符处被截断。
我正在使用 memcpy 将记录缓冲区复制到 Python 返回区域。我认为 memcpy 复制了指定的字节数,而不管内容如何。
我不是 C++ 程序员,所以我很可能误解了 memcpy 的工作原理。
以下代码 sn-ps 是测试代码示例,将演示我遇到的问题。
这是 DLL:
#include "pch.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
#define LIBDLL extern "C" __declspec(dllexport)
LIBDLL int readData_VPRI2(char* buffer, unsigned long buffer_length )
{
char unsigned buf[20];
int unsigned buf_len;
FILE* stream;
errno_t err;
err = fopen_s(&stream, "D:\\testfile", "rb");
if (err != 0) return err;
fread(buf, buffer_length, 1, stream);
memcpy(buffer, buf, buffer_length);
return 0;
}
这是 Python 调用例程:
import ctypes
from ctypes import *
dll = ctypes.CDLL('C:\\Users\\rhkea\\source\\repos\\TestDLL\\x64\\Debug\\TestDLL.dll')
f = open("D:\\testfile", "wb")
test_string = bytes('ABCD\x00efg', encoding='utf-8')
f.write(test_string)
f.close()
char_arr = ctypes.c_char * 500 # set up the return area
buffer = char_arr() # assign the buffer
readData_VPRI2 = dll.readData_VPRI2 # get the DLL
readData_VPRI2.restype = ctypes.c_int # set the return type
readData_VPRI2.argtypes = (POINTER(c_char), c_long) # define the arguments
rc = readData_VPRI2(buffer, len(test_string)) # call the DLL
print ("rc =", rc)
if rc==0:
print ("buffer =", buffer.value)
print ("buffer length = ", len(buffer.value))
Python 执行的输出是:
rc = 0
buffer = b'ABCD'
buffer length = 4
如图所示,返回的缓冲区在 x'00' 处被截断。
我猜我可能会忽略或不理解一些简单的事情。任何有关如何纠正此问题的指导将不胜感激。
提前致谢。
【问题讨论】:
-
sizeof(buffer)不是缓冲区大小,而是指针的大小。结果真的是在\x00处截断吗?如果test_string是'AB\x00CDefg'怎么办? -
谢谢@MikeCAT。我对 sizeof 不好...我更改了上面的代码示例。将流更改为
test_string = bytes('AB\x00CDefg', encoding='utf-8')会导致:rc = 0 buffer = b'AB' buffer length = 2