【问题标题】:Why does this extern "C" function not work using python ctypes?为什么这个 extern "C" 函数不能使用 python ctypes 工作?
【发布时间】:2012-03-19 03:40:12
【问题描述】:

我有以下 c++ 函数,它使用字符串设置整数。

#include <sstream>
#include <string>
#include <iostream>
using namespace std;

extern "C" {
  int a() {
    int number;
    string value("100");
    std::istringstream strm(value);
    strm >> number;
    if (strm.fail()) {
      cout << "Ouch!" << endl;
    }
    else {
      cout << "Number set to:" << number << endl;
    };
    return (int)strm.bad();
  }
}

int main(int argc, char **argv)
{
  a();
}

如果我把它编译成一个程序,它就可以工作。

$ g++ ./streamtest.cc -o streamtest;./streamtest
Number set to:100

但是,如果我从 ctypes 调用相同的函数,它不会设置整数并且“strm”处于“坏”状态。

$ g++ -shared streamtest.cc  -o libstreamtest.so
$ python -c "import ctypes;a = ctypes.CDLL('libstreamtest.so').a();print 'Got [%s] from a()' %a"
Ouch!
Got [1] from a()

这让我很困惑。如何让这个函数在 ctypes 下工作?

【问题讨论】:

  • 可能是python库加载器没有正确调用标准库流所需的一些全局/静态构造函数?
  • 您是否尝试过单步执行并比较它们开始偏离的位置?
  • strm有错误功能吗? (在 strm.fail() 之后打印错误)
  • 它适用于 Windows 7 x64。 (x86 构建)
  • 我尝试单步执行 python -> c++ 代码,但当我尝试从 python 单步执行 a() 时,gdb (7.3) 会引发核心转储。我还检查了 vallgrind。我找不到 istringstream 类的错误函数。

标签: c++ macos ctypes istringstream


【解决方案1】:

它适用于我在使用 x86 构建的 Windows 7 (x64) 上。您是否尝试过用 C 包装代码以用作 Python 的模块?也许这对你有用..

C:\Users\niklas\Desktop>g++ -o streamtest.pyd -shared -I"C:\Python27\include" -L"C:\Python27\libs" streamtestmodule.cpp -lpython27


C:\Users\niklas\Desktop>python
Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import streamtest
>>> streamtest.a()
Number set to:100
0

#include <Python.h>
#include "streamtest.cpp"

extern "C" {

static PyObject* streamtest_a(PyObject* self) {
    PyObject* re = Py_BuildValue("i", a());
    return re;
}

static PyMethodDef StreamtestMethods[] = {
    {"a", (PyCFunction) streamtest_a, METH_NOARGS, NULL},
    {NULL, NULL, 0, NULL}
};


void initstreamtest(void) {
    PyObject* module = Py_InitModule("streamtest", StreamtestMethods);
    if (module == NULL) {
        cout << "Module initialization failed.";
    }
}

} // extern "C"

【讨论】:

  • 谢谢,我也试过python模块版本。它给出了同样的错误。我还尝试了不同的 python 解释器和 g++ 版本,但都给出了相同的错误。我还尝试了不同的 OSX 版本(10.7 与 10.6),但在 10.7 中没有出现错误。
  • 显然这是一个 OSX g++-4.2 错误。它是confirmed by apple,但除了手动删除GLIBCXXDEBUG 定义之外,没有简单的方法可以绕过它。我设法通过使用 llvm-g++ 为 OSX 10.6 编译来解决它。将来我会尝试使用来自 macports 的最新 g++ 编译所有东西(包括 python)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-04
相关资源
最近更新 更多