【问题标题】:pybind11 conflict with GetModuleFileNamepybind11 与 GetModuleFileName 冲突
【发布时间】:2022-01-17 04:36:00
【问题描述】:

我正在使用 pybind11 让 python 调用现有的 C++ 模块(库)。但是,在 C++ 库中,连接是通过调用 ::GetModuleFileName (Visual Studio) 来确定加载模块在 C++ 中运行时的物理路径。但是当我通过pybind11从python(Jupyter Notebook)调用库时,会返回python.exe的物理路径。如何配置或更改以确保获取C++库的物理路径?

C++ 代码是这样的: Lib.h

#pragma once

void run();

Lib.cpp

#include <fstream>
#include <stdexcept>

#include <windows.h>
#include "libloaderapi.h"

#include "Lib.h"

void run()
{
    char buf[1024];
    ::GetModuleFileName(0, buf, sizeof(buf));

    std::ofstream of;
    of.open("logging.txt");

    if (!of.is_open()) {
        throw std::runtime_error("Cannot open logging.txt");
    }

    of << "The loaded module is " << buf << std::endl;
}

pybind11接口代码: 直接.cpp

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>

#include "Lib.h"

namespace py = pybind11;

// wrap c++ function
void wrapper() {
    run();
}

PYBIND11_MODULE(run_app, m) {
    // optional module docstring
    m.doc() = "pybind11 plugin";

    m.def("run", &wrapper, "Run C++ Application");
}

pybind11 安装文件: 设置.py

#from distutils.core import setup, Extension
#from distutils import sysconfig

from setuptools import setup, Extension
import pybind11

# The following is for GCC compiler only.
#cpp_args = ['-std=c++11', '-stdlib=libc++', '-mmacosx-version-min=10.7']
cpp_args = []

sfc_module = Extension(
    'run_app',
    sources=['Direct.cpp', 
             'Lib.cpp'],
    include_dirs=[pybind11.get_include(), '.'],
    language='c++',
    extra_compile_args=cpp_args,
    )

setup(
    name='run_app',
    version='1.0',
    description='Python package with RunApp C++ extension (PyBind11)',
    ext_modules=[sfc_module],
)

构建:

python setup.py 构建

调用这个库的python代码: py_run_app.py

import os
import sys
sys.path.append(os.path.realpath('build\lib.win-amd64-3.7'))

from run_app import run
run()

运行后:

python py_run_app.py

在logging.txt中 加载的模块是 C:....\python.exe

我想看的是模块的物理位置。

【问题讨论】:

  • 显示代码;只要 GetModuleFileName 调用位于 c++ 库中,它就应该返回正确的路径。
  • 如果我错了,请纠正我,但documentation 似乎是说,当使用 NULL 的第一个参数调用时,您将获得可执行文件的路径。
  • 它的行为如记录,在 MSDN 中验证。我认为有一些实际的方法可以处理“当前”模块。除此之外,当DllMain() 被执行时,你也许可以存储句柄。

标签: python c++ visual-studio pybind11


【解决方案1】:

Windows 用语中的“模块”是加载为进程一部分的 DLL 或可执行文件。每个模块都有一个模块句柄;按照惯例,特殊句柄NULL 表示用于创建进程的可执行文件。

GetModuleFileName 需要模块句柄作为第一个参数。你通过0,你会得到带有特殊句柄NULL的模块名称,即可执行文件。这是完全可以预料的。

为了得到一个DLL的文件名,你需要找出它的句柄是什么。可以找到当前模块的句柄:

HMODULE handle;
static char local;
bool ok = GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
                             (LPCSTR)&local,
                             &handle);

local 可以是当前模块中的任何函数或静态/外部变量。 ref.

【讨论】:

  • 这很有帮助,解决了我的问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 2020-03-13
  • 1970-01-01
  • 2013-04-29
  • 1970-01-01
  • 2017-12-09
  • 2013-10-21
  • 2020-08-19
  • 2010-12-10
相关资源
最近更新 更多