Ctypes:将指针传递到使用sprintf 编辑#0

我正在尝试使用Ctypes为预写的DLL文件编写Python包装器,但一直在处理指针问题。

具体地说,已编译到DLL中的C ++函数的简化示例是:

double compute_result(double var1,double var2,char *output_message1,char *output_message2){
    // Computational steps are all here,e.g.
    double result = var1 + var2;

    // then an information message is passed to the output_message1 & 2 location
    sprintf(output_message1,"useful output message 1");
    sprintf(output_message2,"useful output message 2");

    return(result);
}

要使用ctypes包装它,我尝试如下定义适当的restype和argtype。 C ++代码没有为输出消息指针指定大小,因此我假设我不必使用ctypes。

dll = ctypes.WinDLL("MyDLL.dll")
f = dll.compute_result
f.restype = c_double
f.argtypes = [c_double,c_double,POINTER(c_char),POINTER(c_char)]

然后我尝试使用以下命令在Python中调用我的代码:

# Imports
import ctypes
from ctypes import c_double,c_char,POINTER,addressof,cast

# Input variables
var1 = 1.1
var2 = 2.2

# Create string buffers to hold output message,then convert address to a pointer to pass to dll function
size = 1024  # we know output messages will be shorter than 1024 characters
buf1 = ctypes.create_string_buffer(size)
buf2 = ctypes.create_string_buffer(size)

f(var1,var2,cast(addressof(buf1),POINTER(c_char)),cast(addressof(buf2),POINTER(c_char)))

不幸的是,执行时显示对话框错误,提示:

"Debug Assertion Failed!"

Program: ...somepath_on_my_computer\python.exe
File: ...somepath_on_my_computer\sprintf.c
Line: 110

Expression: (string != NULL)

我知道这意味着我的指针存在一些错误,其中sprintf也打算写入输出消息,但是我看不出到底是什么错误。 有办法解决这个问题吗?还是我处理指针不正确?谢谢!

mm6yuz 回答:Ctypes:将指针传递到使用sprintf 编辑#0

列出[Python 3.Docs]: ctypes - A foreign function library for Python

buf1 buf2 (位于基础 C 中)被视为数组,因此它们已经是地址

摆脱 addressof ,因为它会触发未定义行为(选中[SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer))。

尝试:

f(var1,var2,cast(buf1,POINTER(c_char)),cast(buf2,POINTER(c_char)))

有关更高级的示例,请选中[SO]: How can i cast a double pointer ctype to numpy array? (@CristiFati's answer)

编辑#0

添加代码示例。

dll00.c

#include <stdio.h>

#if defined(_WIN32)
#  define DLL00_EXPORT_API __declspec(dllexport)
#else
#  define DLL00_EXPORT_API
#endif


#if defined(__cplusplus)
extern "C" {
#endif

DLL00_EXPORT_API double dll00Func00(double var1,double var2,char *pMsg1,char *pMsg2);

#if defined(__cplusplus)
}
#endif


double dll00Func00(double var1,char *pMsg2) {
    double result = var1 + var2;
    sprintf(pMsg1,"useful output message 1");
    sprintf(pMsg2,"useful output message 2");
    return result;
}

code00.py

#!/usr/bin/env python3

import sys
import ctypes as ct


DLL_NAME = "./dll00.dll"


def main():
    dll00 = ct.CDLL(DLL_NAME)
    dll00Func00 = dll00.dll00Func00
    dll00Func00.argtypes = [ct.c_double,ct.c_double,ct.POINTER(ct.c_char),ct.POINTER(ct.c_char)]
    dll00Func00.restype = ct.c_double

    v1 = 1.1
    v2 = 2.2
    size = 1024
    buf1 = ct.create_string_buffer(size)
    buf2 = ct.create_string_buffer(size)

    res = dll00Func00(v1,v2,ct.cast(buf1,ct.POINTER(ct.c_char)),ct.cast(buf2,ct.POINTER(ct.c_char)))
    print("{0:s} returned: {1:.3f}".format(dll00Func00.__name__,res))
    print(buf1.value,buf2.value)


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")),64 if sys.maxsize > 0x100000000 else 32,sys.platform))
    main()
    print("\nDone.")

输出

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q058932240]> sopr.bat
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***

[prompt]> "c:\Install\x86\Microsoft\Visual Studio Community\2017\VC\Auxiliary\Build\vcvarsall.bat" x64
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.17
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

[prompt]> dir /b
code00.py
dll00.c

[prompt]> cl /nologo /MD /DDLL dll00.c  /link /NOLOGO /DLL /OUT:dll00.dll
dll00.c
   Creating library dll00.lib and object dll00.exp

[prompt]> dir /b
code00.py
dll00.c
dll00.dll
dll00.exp
dll00.lib
dll00.obj

[prompt]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py
Python 3.7.3 (v3.7.3:ef4ec6ed12,Mar 25 2019,22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32

dll00Func00 returned: 3.300
b'useful output message 1' b'useful output message 2'

Done.

请注意,在构建 .dll 进行调试时,它也适用。

本文链接:https://www.f2er.com/3074261.html

大家都在问