pybind11 与 GetModuleFileName 冲突
pybind11 conflict with GetModuleFileName
我正在使用 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接口代码:
Direct.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 安装文件:
setup.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 build
调用这个库的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
我想看的是模块的物理位置。
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
可以是当前模块中的任何函数或 static/extern 变量。 ref.
我正在使用 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接口代码: Direct.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 安装文件: setup.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 build
调用这个库的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
我想看的是模块的物理位置。
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
可以是当前模块中的任何函数或 static/extern 变量。 ref.