3

I have the following c++ function that sets an integer using a string.

#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();
}

If I compile this as a program it works.

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

But if I call the same function from ctypes it does not set the integer and the "strm" is left in a "bad" state.

$ 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()

This got me puzzled. How can I make this function work under ctypes?

SiggyF
  • 22,088
  • 8
  • 43
  • 57
  • could it be that the python library loader isn't properly calling some global/static constructors needed by the standard library's streams? – Evan Teran Feb 29 '12 at 16:21
  • have you tried single stepping both and comparing where they start to deviate? – PlasmaHH Feb 29 '12 at 16:26
  • 1
    does strm have an error function? (one that prints the error after strm.fail()) – KevinDTimm Feb 29 '12 at 16:28
  • 1
    It works on on windows 7 x64. (x86 build) – Niklas R Feb 29 '12 at 16:52
  • I tried to step through the python -> c++ code but gdb (7.3) throws a core dump when I try to step into a() from python. I also checked with vallgrind. I could not find an error function for the istringstream class. – SiggyF Feb 29 '12 at 16:57
  • It might be related to this bug in g++ 4.2 (which ships with OSX10.6) https://discussions.apple.com/thread/2214707?start=0&tstart=0 – SiggyF Feb 29 '12 at 20:02

1 Answers1

1

It works for me on Windows 7 (x64) using x86 build. Have you tried wrapping the code with C for use as module with Python? Maybe that does work for you..

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"
Niklas R
  • 16,299
  • 28
  • 108
  • 203
  • Thanks, I also tried the python module version. It gives the same error. I also tried different python interpreters and g++ versions, but all give the same error. I also tried a different OSX version (10.7 versus 10.6), I don't get the error in 10.7. – SiggyF Feb 29 '12 at 19:58
  • 1
    Apparently it is an OSX g++-4.2 bug. It is [confirmed by apple](https://discussions.apple.com/thread/2214707?start=0&tstart=0) but there's no easy way around it, other than removing `GLIBCXXDEBUG` defines manually. I managed to work around it by compiling using *llvm-g++* for OSX 10.6. In the future I'll try to compile everything (including python) using the latest g++ from macports. – SiggyF Feb 29 '12 at 21:11