Also hier mal der C++Source um das Python-Modul und die funktion zu laden:
Code: Alles auswählen
void func(std::string _module, char* _arg ...) {
std::vector<std::string> py_args;
std::vector<std::string> arguments;
std::string bak_dir = "";
va_list ap; // will point to each unnamed argument in turn
int num;
double d;
std::string s;
char* ss;
const char *p=_arg;
va_start(ap, _arg); // point to first element after _arg
while(*p) {
switch(*p) {
case 'i': // int
num=va_arg(ap,int);
py_args.push_back(NodeConfigFunctions::LongToStr(num));
//printf("%d",num);
break;
case 'd': //double
d=va_arg(ap,double);
py_args.push_back(NodeConfigFunctions::LongToStr(d));
//printf("%f",d);
break;
case 's': // char*
ss=va_arg(ap,char*);
s = ss;
py_args.push_back(s);
//printf("%s",s.c_str());
break;
case 'S': // std::string
s=va_arg(ap,std::string);
py_args.push_back(s);
//printf("%s",s.c_str());
break;
default:
printf("unsupported format flag");
}
++p;
}
va_end(ap); //cleanup
try {
if(py_args.empty())
throw FileError("Cannot find any functions");
std::string py_module_name = _module;
std::string py_function = py_args[0];
py_args.erase(py_args.begin());
PyObject *pName, *pModule, *pDict, *pFunc;
PyObject *pArgs, *pValue, *pValueRepr;
pName = PyString_FromString(py_module_name.c_str());
/* Error checking of pName left out */
// Change the module directory and remember the current directory
if(!this->directory.empty()) {
bak_dir = _getcwd(NULL, 0);
_chdir(this->directory.c_str());
}
// Import python module
pModule = PyImport_Import(pName);
// Change to the previous directory
if(!this->directory.empty())
_chdir(bak_dir.c_str());
if (pModule != NULL) {
// pFunc is a new reference
pFunc = PyObject_GetAttrString(pModule, py_function.c_str());
if (pFunc && PyCallable_Check(pFunc)) {
pArgs = PyTuple_New(py_args.size());
for (int i = 0; i < py_args.size(); ++i) {
//pValue = PyInt_FromLong(atoi(py_arguments[i].c_str()));
pValue = PyString_FromString(py_args[i].c_str());
if (!pValue) {
//Py_DECREF(pArgs);
//Py_DECREF(pModule);
/* fprintf(stderr, "Cannot convert argument\n");
return 1;*/
char buffer[2048] = {0};
sprintf(buffer, "Cannot convert argument\n");
throw FileError(buffer);
}
/* pValue reference stolen here: */
PyTuple_SetItem(pArgs, i, pValue);
}
pValue = PyObject_CallObject(pFunc, pArgs);
pValueRepr = PyObject_Repr(pValue);
//Py_DECREF(pArgs);
if (pValue != NULL) {
std::string value = PyString_AsString(pValueRepr);
trim(value, '\"');
printf("%s\n", value.c_str());
//Py_DECREF(pValue);
}
else {
//Py_DECREF(pFunc);
//Py_DECREF(pModule);
PyErr_Print();
/*fprintf(stderr,"Call failed\n");
_sleep(5000);
return 1;*/
char buffer[2048] = {0};
sprintf(buffer, "Call failed\n");
throw FileError(buffer);
}
}
else {
if (PyErr_Occurred()) {
PyErr_Print();
//_sleep(5000);
}
/*
fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]);
_sleep(5000);*/
char buffer[2048] = {0};
sprintf(buffer, "Cannot find function \"%s\"\n", py_function.c_str());
throw FileError(buffer);
}
}
else {
PyErr_Print();
char buffer[2048] = {0};
sprintf(buffer, "Failed to load \"%s\"\n", py_module_name.c_str());
throw FileError(buffer);
/*fprintf(stderr, "Failed to load \"%s\"\n", argv[1]);
_sleep(5000);
return 1;*/
}
Py_Finalize();
}
catch(FileError &e) {
cerr << e.what() << endl;
}
}
Was möchte ich machen?
ich will von C++ aus Python scripts ausführen und deren return values in C++ weiterverarbeiten. Mit Statischen typen funktioniert und ist mehr oder weniger ein kinderspiel. Mir geht es um dynamisches Datentypen die mir vorher nicht bekannt sind.
Beispiel was funktioniert (sehr "simple" beispiel):
TypA (von C++) = string oder int, ...
TypB (VonPython) = string oder int, ...
1.) C++ (TypA) => übergabe an Python(TypB)
2.) Result von Python(TypB) => übergabe an C++ (TypA)
3.) weiterverwendung von TypA...
aufruf unter c++:
testmodul.py:
So in diesem Beispiel wären mir also unter C++ folgende Funktionen bekannt:
C++ => Python ... PyString_ToString
Python => C++ ... PyString_AsString
Für int, float usw. gibts equivalente Funktionen
Jetzt hat aber ein Programmierer ein Python script hinzugefügt, welches einen Int zurückliefert.
Nun habe ich dann ein Problem, weil PyString_AsString nicht funktioniert, stattdessen müsste ich die Funktion PyInt_AsString verwenden.
Nur vorher weiß ich was für einen Typ ich zurückbekomme?
bzw. wie weiß ich was für einen Typ ich übergebe?
Beispiel:
Code: Alles auswählen
def myFunc(arg):
if(arg == "test1"):
return 1
elif(arg == "test2"):
return 2
else:
return 0
Hier müsste ich PyString_ToString und von Python nach C++ zurück PyInt_AsInt verwenden, nur woher weiß ich das.
Kann man irgendwie ermitteln welchen Typ das PyObject hat und dieses dann dementsprechend casten?
Und/Oder kann man ermitteln welche typen eine funktion benötigt?
Lg NoRulez[/code]