I am using PyUnicode_FromString() and PyUnicode_AsUTF8() while doing python extension from CPP, which is crashing when we use more than one thread .
Is PyUnicode_FromString() and PyUnicode_AsUTF8() thread safe ?
predictGplaceBoxClockregion(int iterationNo,
std::string y_value,
std::string gplaceFeatureFile,
int levelNo,
bool analytical)
{
std::string result = "";
PyObject *d = PyDict_New();
if (iterationNo == 1) {
y_value = "ClockRegion_MultiLabel_iter1";
} else {
y_value = "ClockRegion_MultiLabel_iter2";
}
PyDict_SetItemString(d, "ip", PyUnicode_FromString(gplaceFeatureFile.c_str()));
PyDict_SetItemString(d, "y", PyUnicode_FromString(y_value.c_str()));
PyDict_SetItem(d, PyUnicode_FromString("iterNo"), PyLong_FromLong(iterationNo));
PyObject *methodcall = PyObject_CallMethod(instance, "bindScript", "O", d);
if ( methodcall == nullptr) {
PyErr_Print();
}
result = PyUnicode_AsUTF8(methodcall);
Py_DECREF (d);
return result;
}
Related
I am testing just a small change to this code here: https://github.com/Roffild/RoffildLibrary/blob/master/Libraries/Roffild/PythonDLL/mql_class.c
but it raised exception that I couldn't catch. Anybody has a clue why at least from a look at the code?
I modified a few places to make these 2 new methods compiled ok: the pyMQL_send just crashed without meaning full message while the pyMQL_test raised "SystemError: null argument to internal routine"
_DLLSTD(mqlint) pyMQL_send(const mqllong magic, const mqlstring value,
const mqldouble _DLLOUTARRAY(inputs), const mqlint inputs_size,
mqlstring _DLLOUTSTRING(buffer), const mqlint stringBufferLen)
{
PyObject *arg1 = NULL;
PyObject *arg2 = NULL;
PyObject *arg3 = NULL;
PyObject *result = NULL;
PyObject **items = NULL;
Py_ssize_t x, size;
mqlstring str;
mqlint ret = -1;
PY_THREAD_START_OR(return ret);
PyErr_Clear();
arg1 = PyLong_FromLongLong(magic);
arg2 = PyUnicode_FromWideChar(value, -1);
arg3 = PyTuple_New(inputs_size);
if (arg1 != NULL && arg2 != NULL && arg3 != NULL) {
items = PySequence_Fast_ITEMS(arg3);
for (x = 0; x < inputs_size; x++) {
items[x] = PyFloat_FromDouble(inputs[x]);
}
result = PyObject_CallFunctionObjArgs(__interp->mql_send, arg1, arg2, arg3, NULL);
if (result != NULL) {
Py_DECREF(arg1);
arg1 = PyObject_Str(result);
str = PyUnicode_AsUnicodeAndSize(arg1, &size);
ret = (mqlint)size;
if (size > stringBufferLen) {
size = stringBufferLen;
}
wmemcpy(buffer, str, size);
buffer[size] = 0;
}
}
Py_XDECREF(arg1);
Py_XDECREF(arg2);
Py_XDECREF(arg3);
Py_XDECREF(result);
PY_THREAD_STOP;
return ret;
}
// altered from _getDouble
_DLLSTD(mqlint) pyMQL_test(const mqllong magic, const mqlstring value,
const mqldouble _DLLOUTARRAY(inputs), const mqlint inputs_size,
mqldouble _DLLOUTARRAY(outputs), const mqlint outputs_size)
{
PyObject* arg1 = NULL;
PyObject* arg2 = NULL;
PyObject* arg3 = NULL;
PyObject* result = NULL;
PyObject* seq = NULL;
PyObject** items = NULL;
Py_ssize_t x, size;
mqlint ret = -1;
PY_THREAD_START_OR(return ret);
PyErr_Clear();
arg1 = PyLong_FromLongLong(magic);
arg2 = PyUnicode_FromWideChar(value, -1);
arg3 = PyTuple_New(inputs_size);
if (arg1 != NULL && arg2 != NULL && arg3 != NULL) {
items = PySequence_Fast_ITEMS(arg3);
for (x = 0; x < inputs_size; x++) {
items[x] = PyFloat_FromDouble(inputs[x]);
}
result = PyObject_CallFunctionObjArgs(__interp->mql_test, arg1, arg2, arg3, NULL);
if (result != NULL) {
if (result == Py_None) {
ret = 0;
}
else {
seq = PySequence_Fast(result, "This is not PySequence.");
if (seq != NULL) {
size = PySequence_Fast_GET_SIZE(seq);
ret = (mqlint)size;
if (size > outputs_size) {
size = outputs_size;
}
items = PySequence_Fast_ITEMS(seq);
for (x = 0; x < size; x++) {
outputs[x] = PyFloat_AsDouble(items[x]);
}
}
}
}
}
Py_XDECREF(arg1);
Py_XDECREF(arg2);
Py_XDECREF(arg3);
Py_XDECREF(result);
Py_XDECREF(seq);
PY_THREAD_STOP;
return ret;
}
I've been struggling to have some generic method of iterating over a sequence or iterable in the Cpython C API. The example code below compiles without errors, but fails when run as follows:
it ok
Segmentation fault: 11
I'm speculating that it's failing at the while ((item = PyIter_Next(it))) line but this is hardly controversial since the equivalent python is pretty standard:
x = [1,2,3]
it = iter(x)
for i in it:
print(i)
Clearly, I'm doing something wrong with the c equivalent. Any help or guidance would be most appreciated!
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program);
Py_Initialize();
// create list
PyObject *list = PyList_New(2);
PyObject *n1 = PyLong_FromLong(1);
PyObject *n2 = PyLong_FromLong(2);
PyList_Append(list, n1);
PyList_Append(list, n2);
PyObject *it = PyObject_GetIter(list);
PyObject *item;
int i = 0;
if (it) {
printf("it ok\n");
while ((item = PyIter_Next(it))) {
if (PyLong_Check(item)) {
i++;
long long_item = PyLong_AsLong(item);
printf("%d long: %ld", i, long_item);
} else if PyFloat_Check(item) {
i++;
float float_item = PyFloat_AsDouble(item);
printf("%d float: %f", i, float_item);
} else if PyUnicode_Check(item) {
i++;
const char *unicode_item = PyUnicode_AsUTF8(item);
printf("%d unicode: %s", i, unicode_item);
} else continue;
Py_DECREF(item);
Py_DECREF(it);
}
} else {
if (PyErr_Occurred()) {
PyErr_Print();
}
Py_DECREF(n1);
Py_DECREF(n2);
Py_DECREF(list);
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
}
In response to #DavidW's helpful observation of my error, here is the corrected code which could perhaps be a helpful example to others.
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program);
Py_Initialize();
// create list
PyObject *list = PyList_New(0); // empty list
PyObject *n1 = PyLong_FromLong(10);
PyObject *n2 = PyLong_FromLong(20);
PyList_Append(list, n1);
PyList_Append(list, n2);
PyObject *iter;
PyObject *item;
int i = 0;
if ((iter = PyObject_GetIter(list)) == NULL) {
return -1;
}
while ((item = PyIter_Next(iter)) != NULL) {
if (PyLong_Check(item)) {
i++;
long long_item = PyLong_AsLong(item);
printf("%d long: %ld\n", i, long_item);
}
if PyFloat_Check(item) {
i++;
float float_item = PyFloat_AsDouble(item);
printf("%d float: %f\n", i, float_item);
}
if PyUnicode_Check(item) {
i++;
const char *unicode_item = PyUnicode_AsUTF8(item);
printf("%d unicode: %s\n", i, unicode_item);
}
Py_DECREF(item);
}
Py_DECREF(iter);
Py_DECREF(n1);
Py_DECREF(n2);
Py_DECREF(list);
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
PyObject *list = PyList_New(2);
This creates a list with length 2, and with uninitialized contents (probably NULL pointers, but I'm not 100% sure).
PyList_Append(list, n1);
PyList_Append(list, n2);
These append to the end of the list (i.e. positions 3 and 4).
Therefore you have a list of <garbage>, <garbage>, n1, n2.
You either replace the PyList_Append with PyList_SetItem, or replace PyList_New(2) with PyList_New(0).
Py_DECREF(it);
should be done once the iteration has finished, not in the loop.
I'm using embedded python interpreter in my app (iOS to be detailed).
Sometimes sys.exit(1) is invoked in interpreted script and it finishes the whole app process instead of stopping PyObject_callObject() invocation. I've tried to check errors using PyErr_Occured but it did not help.
How to prevent sys.exit(N) to finish the whole process in embedded python?
NSString *outputFile = nil;
for (int i=0; i<args.count; i++) {
if ([#"-o" isEqualToString:args[i]]) {
outputFile = args[i + 1];
break;
}
}
PyEval_AcquireLock();
PyThreadState *subState = Py_NewInterpreter();
PyObject *pModuleName, *pModule, *pFunc;
// init python
NSString *pythonHome = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:#"/"];
Py_SetProgramName("python");
char *cPythonHome = (char*)[pythonHome UTF8String];
setenv("PYTHONPATH", cPythonHome, 1); // VERY IMPORTANT !!!
Py_SetPythonHome(cPythonHome);
NSString *libsPath = [pythonHome stringByAppendingString:#"lib/python2.7"];
if (!Py_IsInitialized())
Py_Initialize();
// invoke
int result = 0;
NSString *scriptFilename = args[1];
NSString *moduleName = [[scriptFilename lastPathComponent] stringByDeletingPathExtension];
pModuleName = PyString_FromString([moduleName UTF8String]); // module (script) name
pModule = PyImport_Import(pModuleName);
if (PyErr_Occurred())
PyErr_Print();
if (pModule != NULL) {
pFunc = PyObject_GetAttrString(pModule, "main__"); // module must have "def main__(args)"
if (pFunc != NULL && PyCallable_Check(pFunc)) {
// prepare args
PyObject *pArgs = PyList_New(args.count-1);
for (int i=0; i<args.count-1; i++) {
NSString *arg_i = args[i + 1]; // skip first argument (it's program name)
PyObject *pEachArg = PyString_FromString([arg_i UTF8String]);
PyList_SetItem(pArgs, i, pEachArg);
// WARNING: don't Py_DECREF for each argument
}
// for some reason arguments should be passed as s Tuple
PyObject *pTuple = PyTuple_New(1);
PyTuple_SetItem(pTuple, 0, pArgs);
// call func
NSLog(#"Invoke %# via main__(args)", scriptFilename);
PyObject *pyResult = PyObject_CallObject(pFunc, pTuple); // process killed here !
if (pyResult == NULL || PyErr_Occurred()) {
// print error
PyErr_Print();
// fix error
PyErr_Clear();
if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
result = 3; // error: system.exit() called
} else
result = 4; // error: unknown exception
}
if (pyResult != NULL)
Py_DECREF(pyResult);
Py_DECREF(pTuple);
Py_DECREF(pArgs);
} else
result = 2; // error: can't find "def main__()" in module
if (pFunc != NULL)
Py_XDECREF(pFunc);
} else
result = 1; // error: can't import module
if (pModule != NULL)
Py_DECREF(pModule);
Py_DECREF(pModuleName);
// restore parent interpreter
Py_EndInterpreter(subState);
PyEval_ReleaseLock();
I had to hack Python sources and create my own function:
int MyPyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, PyCompilerFlags *flags)
{
PyObject *m, *d, *v;
const char *ext;
int set_file_name = 0, ret, len;
m = PyImport_AddModule("__main__");
if (m == NULL)
return -1;
d = PyModule_GetDict(m);
if (PyDict_GetItemString(d, "__file__") == NULL) {
PyObject *f = PyString_FromString(filename);
if (f == NULL)
return -1;
if (PyDict_SetItemString(d, "__file__", f) < 0) {
Py_DECREF(f);
return -1;
}
set_file_name = 1;
Py_DECREF(f);
}
len = strlen(filename);
ext = filename + len - (len > 4 ? 4 : 0);
/*
if (maybe_pyc_file(fp, filename, ext, closeit)) {
// Try to run a pyc file. First, re-open in binary
if (closeit)
fclose(fp);
if ((fp = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "python: Can't reopen .pyc file\n");
ret = -1;
goto done;
}
// Turn on optimization if a .pyo file is given
if (strcmp(ext, ".pyo") == 0)
Py_OptimizeFlag = 1;
v = run_pyc_file(fp, filename, d, d, flags);
} else { */
v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d,
closeit, flags);
//}
if (v == NULL) {
//PyErr_Print(); // crashed here!
ret = -1;
goto done;
}
Py_DECREF(v);
if (Py_FlushLine())
PyErr_Clear();
ret = 0;
done:
if (set_file_name && PyDict_DelItemString(d, "__file__"))
PyErr_Clear();
return ret;
}
I had to use _SimpleFile instead of _SimpleString but i believe you can change _SimpleString in similar way.
The reason was PyErr_Print which caused app crash. The one drawback is that i had to comment pyc file checking and usage as maybe_pyc_file is not exported and is unavailable.
One more note: if SystemExit was raised (by sys.exit(1) f.e.) don't use PyErr_Print. Use the next checking:
if (PyErr_Occurred()) {
pythonSuccess = NO;
if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
NSLog(#"sys.exit() in python");
} else {
// print error
PyErr_Print();
}
// fix error
PyErr_Clear();
}
If you have better solution, let us know.
Im not very good with python, but for this project I need to use a python GUI to test my program. Its compiling without any errors, but its giving errors when I go to test it in the GUI. The objective of the program is to create a English to French dictionary from a .txt file that has all the translations/definitions. My code is as follows. If anyone could help, that would be great.
These are the errors I am getting:
Exception in Tkinter callback
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1470, in __call__
return self.func(*args)
File "Dictionary.py", line 33, in <lambda>
lambda e, s=self: s.translate(english, french))
File "Dictionary.py", line 69, in translate
clearall(english, french)
NameError: global name 'clearall' is not defined
For further information, I'm supposed to check these conditions:
1)no command line arguments and 2) unsuccessful file openings.
Dictionary.cpp:
#include "HashTable.h"
#include "DictionaryEntry.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
int main( int argc, char** argv )
{
HashTable <DictionaryEntry> table;
DictionaryEntry dictEntry;
string temp;
string entry;
string translation;
vector <string> engWords;
string uentry;
int randNum;
ifstream inputStream;
//If command line is empty, error
if( argc <= 1)
{
cout << "Invalid entry." << endl;
return 0;
}
inputStream.open(argv[1]);
//If no file is opened, error
/*if( !inputStream )
{
cout << "Invalid file." << endl;
return 0;
}*/
while( !inputStream.eof( ) )
{
getline( inputStream, temp );
unsigned location = temp.find_first_of( '\t' );
entry = temp.substr( 0, location );
int end = temp.length( );
translation = temp.substr( location + 1, end );
dictEntry.set( entry, translation );
table.insert( dictEntry );
engWords.push_back( entry );
}
while( 1 )
{
cout << "Insert english word: ";
cin >> uentry;
DictionaryEntry search;
search.set( uentry, "");
if( uentry == "random" )
{
randNum = rand( ) % engWords.size( );
temp = engWords.at( randNum );
search.set( temp, "" );
dictEntry = table.retrieve( search );
cout << dictEntry.getEntry( ) << endl;
cout << dictEntry.getTranslation( ) << endl;
}
else
{
dictEntry = table.retrieve( search );
if( dictEntry.getEntry( ) != "" )
{
cout << dictEntry.getEntry( ) << endl;
cout << dictEntry.getTranslation( ) << endl;
}
else
{
cout << "\n";
cout << "\n";
}
}
}
}
List.h:
#ifndef LIST_H
#define LIST_H
using namespace std;
template <typename Object>
class List
{
private:
struct Node
{
Object data;
Node *prev;
Node *next;
Node(const Object & d = Object{ }, Node * p = nullptr, Node * n = nullptr )
: data{ d }, prev{ p }, next{ n } { }
Node( Object && d, Node * p = nullptr, Node * n = nullptr )
: data{ std::move( d ) }, prev{ p }, next{ n } { }
};
public:
class const_iterator
{
public:
const_iterator( ) : current{ nullptr }
{ }
const Object & operator* ( ) const
{ return retrieve( ); }
const_iterator & operator++ ( )
{
current = current->next;
return *this;
}
const_iterator operator++ (int)
{
const_iterator old = *this;
++( *this );
return old;
}
bool operator== (const const_iterator & rhs ) const
{ return current == rhs.current; }
bool operator!= ( const const_iterator & rhs ) const
{ return !( *this == rhs ); }
protected:
Node *current;
Object & retrieve( ) const
{return current->data;}
const_iterator(Node *p ) : current{ p }
{ }
friend class List<Object>;
};
class iterator : public const_iterator
{
public:
iterator( )
{ }
Object & operator* ( )
{ return const_iterator::retrieve( ); }
const Object & operator* ( ) const
{ return const_iterator::operator*( ); }
iterator & operator++ ( )
{
this->current = this->current->next;
return *this;
}
iterator operator++ ( int )
{
iterator old = *this;
++( *this );
return old;
}
iterator operator--()
{
const_iterator::current = const_iterator::current->prev;
return *this;
}
iterator operator--(int)
{
iterator old = *this;
--(*this);
return old;
}
protected:
iterator( Node *p ) : const_iterator{ p }
{ }
friend class List<Object>;
};
public:
List( )
{ init( ); }
~List( )
{
clear( );
delete head;
delete tail;
}
List( const List & rhs )
{
init( );
for( auto & x : rhs )
push_back( x );
}
List & operator= ( const List & rhs )
{
List copy = rhs;
std::swap( *this, copy );
return *this;
}
List ( List && rhs )
: theSize{ rhs.theSize }, head{rhs.head }, tail{rhs.tail }
{
rhs.theSize = 0;
rhs.head = nullptr;
rhs.tail = nullptr;
}
List & operator= ( List && rhs )
{
std::swap( theSize, rhs.theSize );
std::swap( head, rhs.head );
std::swap( tail, rhs.tail );
return *this;
}
iterator begin( )
{ return { head->next }; }
const_iterator begin( ) const
{ return { head->next }; }
iterator end( )
{ return { tail }; }
const_iterator end( ) const
{ return { tail }; }
int size( ) const
{ return theSize; }
bool empty( ) const
{ return size( ) == 0; }
void clear( )
{
while( !empty( ) )
pop_front( );
}
Object & front( )
{ return *begin( ); }
const Object & front( ) const
{ return *begin( ); }
Object & back( )
{ return *--end( ); }
const Object & back( ) const
{ return *--end( ); }
void push_front( const Object & x )
{ insert( begin( ), x ); }
void push_front( Object && x )
{ insert( begin( ), std::move( x ) ); }
void push_back( const Object & x )
{ insert( end( ), x ); }
void push_back( Object && x )
{ insert( end( ), std::move( x ) ); }
void pop_front( )
{ erase( begin( ) ); }
void pop_back( )
{ erase( --end( ) ); }
//Insert x before itr
iterator insert( iterator itr, const Object & x )
{
Node *p = itr.current;
theSize++;
return { p->prev = p->prev->next = new Node{ x, p->prev, p } };
}
//Insert x before itr
iterator insert( iterator itr, Object && x )
{
Node *p = itr.current;
theSize++;
return { p->prev = p->prev->next = new Node{ std::move( x ), p->prev, p } };
}
//Erase item at itr
iterator erase( iterator itr )
{
Node *p = itr.current;
iterator retVal{ p->next };
p->prev->next = p->next;
p->next->prev = p->prev;
delete p;
theSize--;
return retVal;
}
iterator erase( iterator from, iterator to )
{
for( iterator itr = from; itr != to; )
itr.erase( itr );
return to;
}
iterator find( const Object & x )
{
iterator start= begin();
while(start!=end()){
if(x==*start)
return start;
start++;
}
return start;
}
/*
iterator find( string & x )
{
iterator start = begin();
while( start != end( ) ) {
if( strcasecmp( x.c_str( ),( *start ).getWord( ).c_str( ) )==0 )
return start;
else
start++;
}
return start;
}
*/
const_iterator find(const Object & x) const
{
const_iterator start=begin();
while(start!=end()){
if(x==*start)
return start;
start++;
}
return start;
}
/*
const_iterator find(const string & x){
const_iterator start = const_iterator(head);
while( start != end()){
if(strcasecmp(x.c_str(),(*start).getWord().c_str())==0)
return start;
else
start++;
}
return start;
}
*/
private:
int theSize;
Node *head;
Node *tail;
void init( )
{
theSize = 0;
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
}
};
#endif
HashTable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <vector>
#include <string>
#include "List.h"
#include "DictionaryEntry.h"
using namespace std;
//checks if a value is prime
bool isPrime(int n){
if( n==2 || n==3)
return true;
if( n==1 || n%2 == 0)
return false;
for(int i=3; i*i<n; i+=2)
if(n%i == 0)
return false;
return true;
}
//finds the next prime number
int nextPrime (int n) {
if( n%2==0)
n++;
while( !isPrime(n))
n+=2;
return n;
}
template <typename HashedObj>
class HashTable
{
public:
//constructor (explicit so no implicit conversion)
explicit HashTable( int size = 3500) : tableSize(size), currentSize(size), theLists(size) { }
//empty the Hashtable
void makeEmpty( )
{
currentSize=0;
//clear each linked list from hastable
for(int i=0; i<tableSize; i++)
theLists[i].clear( );
}
//search for x in Hashtable
bool contains( const HashedObj & x ) const{
//assign reference variable to rename the complicated object
const List<HashedObj> & whichList = theLists[ myhash( x ) ];
//return whether x already exists in the list
return whichList.find( x ) != whichList.end( );
}
//insert x into Hashtable (true if successful, false if already exists)
bool insert( const HashedObj & x ) {
//assign reference variable to rename the complicated object
List<HashedObj> & whichList = theLists[ myhash( x ) ];
//if x already exists in the list, return false
if( whichList.find( x ) != whichList.end() )
return false;
//otherwise push to list
whichList.push_front( x );
//rehash if new size is greater than hashtable size
if( ++currentSize >tableSize ) {
rehash( );
}
return true;
}
//remove x from Hashtable (true if successful, false if not found)
bool remove( const HashedObj & x ) {
//assign reference variable to rename the complicated object
List<HashedObj> & whichList = theLists[ myhash( x ) ];
//iterator is at end of list (i.e., not found)
if( whichList.find(x) == whichList.end() )
return false;
//erase x
whichList.erase( whichList.find (x) );
--currentSize;
return true;
}
HashedObj & retrieve( HashedObj & obj)
{
return *(theLists[myhash(obj)].find(obj));
}
private:
//The vector of linked-lists hashtable
vector<List<HashedObj> > theLists;
int currentSize;
int tableSize;
//Because coming with new stuff is hard <--Haha
void rehash( ){
vector<List<HashedObj> > oldLists=theLists;
int oldtableSize = tableSize;
tableSize = nextPrime( 2* oldtableSize );
//Create new double-sized, empty table
theLists.resize( tableSize );
for( int i=0; i<tableSize; i++ )
theLists[i].clear();
//copy table over
currentSize = 0;
for( int i=0; i<oldtableSize; i++ ){
while( !oldLists[i].empty() ){
insert( oldLists[i].front() );
oldLists[i].pop_front();
}
}
}
//call hash function and makes sure values fit in table
int myhash( const HashedObj & x ) const
{
int hashVal = hash2(x); //call hash function
//make sure the hash values fit into HashTable
hashVal %= tableSize;
if( hashVal < 0 )
{
hashVal += tableSize;
}
return hashVal;
}
/*
int myhash( const string & x ) const
{
int hashVal = hash( x );
hashVal %= tableSize;
if( hashVal < 0 )
{
hashVal += tableSize;
}
return hashVal;
}
*/
};
int hash2( const string & key )
{
int hashVal = 0;
for( int i = 0; i < key.length( ); i++ )
{
hashVal = 37 * hashVal + key[i];
}
return hashVal;
}
int hash2( const DictionaryEntry word )
{
return hash2(word.getEntry());
}
int hash2(int key)
{
return key;
}
#endif
DictionaryEntry.h:
#ifndef DICTIONARYENTRY_H
#define DICTIONARYENTRY_H
#include <string>
#include <iostream>
#include "HashTable.h"
using namespace std;
class DictionaryEntry
{
public:
DictionaryEntry( )
{
entry = "";
translation = "";
}
DictionaryEntry( const DictionaryEntry & rhs )
{
entry = rhs.entry;
translation = rhs.translation;
}
void set( string ent, string trans )
{
entry = ent;
translation = trans;
}
const string & getTranslation( ) const
{
return translation;
}
const string & getEntry( ) const
{
return entry;
}
bool operator== ( const DictionaryEntry & rhs ) const
{
return getEntry( ) == rhs.getEntry( );
}
bool operator!= ( const DictionaryEntry & rhs ) const
{
return (getEntry() != rhs.getEntry() );
}
private:
string entry;
string translation;
};
#endif
and Dictionary.py:
#!/usr/bin/python
from Tkinter import *
import subprocess
# general function for frame generation
def frame(root, side):
w = Frame(root)
w.pack(side=side, expand=YES, fill=BOTH)
return w
# general function for button generation
def button(root, side, text, command=None):
w = Button(root, text=text, command=command)
w.pack(side=side, expand=YES, fill=BOTH)
return w
# main class for GUI
class Translator(Frame):
def __init__(self):
Frame.__init__(self)
self.pack(expand=YES, fill=BOTH)
self.master.title("English-French Translator")
self.master.iconname("English-French Translator")
Label(self, text='English').pack(side=TOP, expand=YES, fill=BOTH)
english = StringVar()
Entry(self, relief=SUNKEN, textvariable=english).pack(side=TOP, expand=YES, fill=BOTH)
buttonsF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Translate')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.translate(english, french))
clearF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Clear')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.clearall(english, french))
randF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Flash Me (TM)')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.random(english, french))
Label(self, text='French').pack(side=TOP, expand=YES, fill=BOTH)
french = StringVar()
Message(self, relief=SUNKEN, textvariable=french, width=200).pack(side=TOP, expand=YES, fill=BOTH)
# clear all text boxes
def clearall(self, english, french):
english.set('')
french.set('')
# translate english to french
def translate(self, english, french):
if (len(english.get()) > 0):
try:
# send english word to subprocess
process.stdin.write('%s\n'%english.get())
# read line of output from subprocess (original text)
original=process.stdout.readline()
# read line of output from subprocess (translated text)
translation=process.stdout.readline()
# set english textbox
english.set(original.rstrip())
# set french textbox
french.set(translation.rstrip())
except:
clearall(english, french)
def random(self, english, french):
try:
process.stdin.write('random\n')
original=process.stdout.readline()
translation=process.stdout.readline()
english.set(original.rstrip())
french.set(translation.rstrip())
except:
clearall(english, french)
if __name__ == '__main__':
args='French.txt'
process=subprocess.Popen('Dictionary %s'%args, shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
Translator().mainloop()
The error message is telling you exactly what's wrong: "global name 'clearall' is not defined". You have to ask yourself, 'why does python think it's not defined?" In this case, the clue is that it thinks clearall is a global function. Why? Because that's how you are using it.
In looking at your code, it appears you have a "clearall" method as part of an object, so likely all you need to do is change clearall(...) to self.clearall(...) everywhere you call clearall.
I'm back to programming in a project and i'm getting no return from the python script for some long hours now.
Funny thing is, a couple of months ago i managed to get this working, now i don't know what's wrong
Where's the C++ code:
int CPythonPlugIn::py_embed(int argc, char *argv[]){
ofstream textfile3;
textfile3.open("FP_python_embed.txt");
PyObject *pName, *pModule, *pDict, *pFunc, *pArgs, *pValue;
if(argc<3){
printf("Usage: exe_name python_source function_name\n");
return 1;
}
//To inform the interpreter about paths to Python run-time libraries
Py_SetProgramName(argv[0]);
// Initialize the Python Interpreter
Py_Initialize();
if( !Py_IsInitialized() ){
cout<<"Can't initialize"<<endl;
return -1;
}
// Build the name object
pName = PyString_FromString(argv[1]);
if( !pName ){
cout<<"Can't build the object "<<endl;
return -1;
}
// Load the module object
pModule = PyImport_Import(pName);
if( !pModule ){
cout<<"Can't import the module "<<endl;
return -1;
}
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
if( !pDict ){
cout<<"Can't get the dict"<<endl;
return -1;
}
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, argv[2]);
if( !pFunc || !PyCallable_Check(pFunc) ){
cout<<"can't get the function"<<endl;
return -1;
}
if (PyCallable_Check(pFunc))
{
// Prepare the argument list for the call
if( argc > 3 )
{
pArgs = PyTuple_New(argc - 3);
for (int i = 0; i < argc - 3; i++)
{
pValue = PyInt_FromLong(atoi(argv[i + 3]));
if (!pValue)
{
PyErr_Print();
return 1;
}
PyTuple_SetItem(pArgs, i, pValue);
}
pValue = PyObject_CallObject(pFunc, pArgs);
textfile3<<PyInt_AsLong(pValue)<<endl<<" worked1";
if (pArgs != NULL)
{
Py_DECREF(pArgs);
}
}
else
{
pValue = PyObject_CallObject(pFunc, NULL);
}
if (pValue != NULL)
{
printf("Return of call : %d\n", PyInt_AsLong(pValue));
textfile3<<PyInt_AsLong(pValue)<<endl<<" worked2";
Py_DECREF(pValue);
}
else
{
PyErr_Print();
}
textfile3.close();
}
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
// Finish the Python Interpreter
Py_Finalize();
return 0;
};
and this is how i call this function:
char *arg[4]={"PythonPlugIn2","bridge","test_callsign","MAH545"};
py_embed(4,arg);
the simple python script:
def test_callsign(b):
fp_txt=open('allomate.txt','w+')
fp_txt.write('WHAT')
fp_txt.write(b)
if b=='MAH545':
fp_txt.write('MAHHH')
fp_txt.close()
return 1
elif b=='MAH544':
fp_txt.close()
return 2
elif b=='AFR545':
fp_txt.close()
return 3
else:
fp_txt.write('MAHHH22')
print 'No such airplane'
fp_txt.close()
return 10
The allomate.txt is created and it has only "WHAT" written on it. The FP_python_embed.txt also is created and has "-1, worked1" so the problem needs to be on pValue which is giving NULL for some reason
Thank you in advance for the help
I finally found the solution. I was parsing the pValue not as a string but as an int.
So, where i had:
pValue = PyInt_FromLong(atoi(argv[i + 3]));
it really should be:
pValue = PyString_FromString(argv[i+3]);