您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

使用C ++项目(Visual Studio)中的参数调用Python函数

使用C ++项目(Visual Studio)中的参数调用Python函数

我尝试使用给定的intel复制问题,但是这是不可能的,因此我创建了一个小示例(尽可能接近问题中所描述的内容)-也称为[SO]:如何创建最小的,可复制的示例(reprex(mcve))(应该包含在问题BTW中

因此,我在这里说明的问题是:

我正在使用(在 Win 10 x64(10.0.16299.125)上 ):

该结构包括

main00.cpp

#include <string>
#include <iostream>

#if defined(_DEBUG)
#  undef _DEBUG
#  define _DEBUG_UNDEFINED
#endif
#include <Python.h>
#if defined(_DEBUG_UNDEFINED)
#  define _DEBUG
#  undef _DEBUG_UNDEFINED
#endif

#define MOD_NAME "experiment_test"
#define FUNC_NAME "function_name"
#define TEST_FILE_NAME "test_dir\\test_file.txt"

using std::cout;
using std::cin;
using std::endl;
using std::string;


int cleanup(const string &text = string(), int exitCode = 1) {
    Py_Finalize();
    if (!text.empty())
        cout << text << endl;
    cout << "Press ENTER to return...\n";
    cin.get();
    return exitCode;
}


int main() {
    char c;
    string fName = TEST_FILE_NAME, result;
    PyObject *pName = NULL, *pModule = NULL, *pDict = NULL, *pFunc = NULL, *pArgs = NULL, *pValue = NULL, *pResult = NULL;
    Py_Initialize();
    pName = PyUnicode_FromString(MOD_NAME);
    if (pName == NULL) {
        return cleanup("PyUnicode_FromString returned NULL");
    }
    pModule = PyImport_Import(pName);
    Py_DECREF(pName);
    if (pModule == NULL) {
        return cleanup(string("NULL module: '") + MOD_NAME + "'");
    }
    pDict = PyModule_GetDict(pModule);
    if (pDict == NULL) {
        return cleanup("NULL module dict");
    }
    pFunc = PyDict_GetItemString(pDict, FUNC_NAME);
    if (pFunc == NULL) {
        return cleanup(string("module '") + MOD_NAME + "' doesn't export func '" + FUNC_NAME + "'");
    }
    pArgs = PyTuple_New(1);
    if (pArgs == NULL) {
        return cleanup("NULL tuple returned");
    }
    pValue = PyUnicode_FromString(fName.c_str());
    if (pValue == NULL) {
        Py_DECREF(pArgs);
        return cleanup("PyUnicode_FromString(2) returned NULL");
    }
    int setItemResult = PyTuple_SetItem(pArgs, 0, pValue);
    if (setItemResult) {
        Py_DECREF(pValue);
        Py_DECREF(pArgs);
        return cleanup("PyTuple_SetItem returned " + setItemResult);
    }
    pResult = PyObject_CallObject(pFunc, pArgs);
    Py_DECREF(pArgs);
    Py_DECREF(pValue);
    if (pResult == NULL) {
        return cleanup("PyObject_CallObject returned NULL");
    } else {
        int len = ((PyASCIIObject *)(pResult))->length;
        char *res = PyUnicode_AsUTF8(pResult);
        Py_DECREF(pResult);
        if (res == NULL) {
            return cleanup("PyUnicode_AsUTF8 returned NULL");
        } else {
            cout << string("C(++) - Python call: ") << MOD_NAME << "." << FUNC_NAME << "('" << fName << "') returned '" << res << "' (len: " << len << ")" << endl;
        }
    }
    return cleanup("OK", 0);
}

开头的 _ *_

如我所说,尝试简化代码(摆脱了 PyCallable_Check 测试)

尽管代码使用 _ *_

由于 Python的API[Python.Docs]:Python嵌入在另一个应用程序)(都伸到/嵌入)使用指针,确保 ,否则有一个高的机会越来越 错误访问冲突

添加[Python.Docs]:参考计数-无效的Py_DECREF(PyObject * o)语句可避免内存泄漏

Build(编译/链接)/ Run选项(显然,您已经跳过了这些,因为您能够运行您的程序,但是无论如何我都会列出它们-确保在处理 时这里有一些捷径这样的项目):

巨集

* 路径(“ _c:\ Install \ x64 \ Python \ Python \ 3.5_ ”)指向从官方站点下载的安装

* 显然,对于 _32bit_ ,必须相应地设置路径(设置为 _32bit_ _Python_ )

* 该路径包含(按预期的方式)一个 _Release_ 版本,并且只要我不需要进入 _Python_ 代码(并且只要我不弄乱内存,就像(在 _Debug中_ 构建我的应用程序时),模式))。我的 _.exe中_ 有2个 _C运行时_ -检查下面的链接,查看篡改 _MSVC运行时_ ( _UCRT_ )会发生什么: __ __ __

  * [[SO]:在库中使用fstream时,可执行文件中出现链接错误(@CristiFati的回答)](https://stackoverflow.com/questions/8528437/when-using-fstream-in-a-library-i-get-linker-errors-in-the-executable/41558269#41558269)
  * [[SO]:链接到MS Visual C上的protobuf 3时出错(@CristiFati的回答)](https://stackoverflow.com/questions/35116437/errors-when-linking-to-protobuf-3-on-ms-visual-c/35118400#35118400)
  * 对于 _特殊_ 情况下,我已经建立 _的Python_ 在 _调试_ 模式,得到了二进制文件,但是这不是我的1日的选择,因为它需要设置(路径)改变
* 编译:

VStudio 知道 Python 包含文件的位置:

包括

* 链接

VStudio 知道 Python文件的位置(如果只需要 pythonxx * .lib ( _ ),则不需要任何额外的操作,因为 _Python 代码认包含 PYTHONCORE ;否则,所有其余的都应在[MS.Docs中](https://docs.microsoft.com/en- us/cpp/build/reference/dot-lib-files-as-linker- input)指定[]:.lib文件作为链接器输入: __

链接

* 运行/调试-让:

  * _VStudio_ 知道 _Python_ 运行时 _ **python35.dll**_ ( _PYTHONCORE_ )所在的位置( _%PATH%_ )
  * 加载的 _Python_ 运行时知道其他模块的位置( _%PYTHONPATH%_ )

调试

Experiment_test.py

import os
import shutil
import codecs


def function_name(file_name):
    print("Py - arg: '{}'".format(file_name))
    if not os.path.isfile(file_name):
        return file_name
    with open(file_name, "rb") as f:
        content = f.read().decode()
        print("Py - Content len: {}, Content (can spread across multiple lines): '{}'".format(len(content), content))
        return content

test_dir \ test_file.txt

line 0 - dummy
line 1 - gainarie

VStudio 控制台):

Py - arg: 'test_dir\test_file.txt'
Py - Content len: 33, Content (can spread across multiple lines): 'line

0 - dummy line 1 - gainarie’ C(++) - Python call: experiment_test.function_name(‘test_dir\test_file.txt’) returned ‘line 0 - dummy line 1 - gainarie’ (len: 33) OK Press ENTER to return…

python 2022/1/1 18:39:05 有258人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶