Cannot call/compile TPython::Exec function in a file

Hello,

This works (root prompt, ROOT 6.08/06):

root [] TPython::Exec("from math import sqrt as sqrt_py");
root [] (double) TPython::Eval("sqrt_py(4.)")
(double) 2.00000

However, if I try to put these lines into a file “tpython_test.h” and compile it:
root [] .x tpython_test.h++

then I get an error:

INFO     creating shared library /home/developer/workspace/code_dev/microsci/parcol/parcol/ampl/cpp/interface/.build_cache_sciutils/sciutils//home/developer/workspace/code_dev/microsci/parcol/parcol/ampl/cpp/interface/./tpython_test_h.so
In file included from input_line_12:9:
././tpython_test.h:6:10: error: C++ requires a type specifier for all declarations
TPython::Exec("from math import sqrt as sqrt_py");
         ^
ERROR    Dictionary generation failed!
Traceback (most recent call last):
  File "_ctypes/callbacks.c", line 315, in 'calling callback function'
  File "/home/developer/workspace/opt/miniconda/envs/microsci/lib/python2.7/site-packages/rootpy/logger/roothandler.py", line 106, in python_logging_error_handler
    caller = sys._getframe(1)
ValueError: call stack is not deep enough

  1. How can I fix the error? #include “TPython.h” is probably not enough to define the Exec function… What do I miss here?
  2. Is there a way how one can call “sqrt_cpp” from the file with “x” argument (sqrt_py is now always calculated for 4)?

Many thanks for any hint! :slight_smile:

Cheers,
Jiri

tpython_test.h (221 Bytes)

Hi Jiri,

this works for me, can you try:

// Compile with g++ -o a a.cpp `root-config --cflags --libs` -lPyROOT
#include "TPython.h"
#include <iostream>

int main(){

TPython::Exec("from math import sqrt as sqrt_py");
std:: cout << Double_t (TPython::Eval("sqrt_py(4.)")) << std::endl;

}

Let me know how it goes.

Cheers,
D

1 Like

And, to edit the value for which you want the square root, you’ll have to do some string manipulation.

Hello,

yes, it works ( the -lPyROOT flag is important). I compiled ROOT with cmake (https://root.cern.ch/building-root) but I don’t see any corresponding option which one could enable (python should be ON by default - at least PyROOT seems to work otherwise fine). Is there any other way how to load the missing library (at compile and/or run time)?

This is how I compile/load a c++ code in my real case:
ROOT.gROOT.ProcessLine('.L file.cpp++')

As to my second question. Yes, some string manipulation should probably work in this special case. But I am wondering if there is better (more general) way to do it. I just found this article: W Lavrijsen, Python in the Cling World, 2015 J. Phys.: Conf. Ser. 664 062029 (http://iopscience.iop.org/article/10.1088/1742-6596/664/6/062029) where on page 3 one can find an example using TPython::Import (which works), but if I try something similar then it fails:

root [] TPython::Import("math")
(Bool_t) true
root [] (double)math::sqrt(3.14)
ROOT_prompt_38:1:20: error: too many arguments to function call, expected 0, have 1
(double)math::sqrt(3.14)
        ~~~~~~~~~~ ^~~~
input_line_90:44:2: note: 'sqrt' declared here
 TPyReturn sqrt() {
 ^
root [] (double)math::sqrt()
TypeError: a float is required
(double) -1.00000

Something like this would be really interesting. In the paper it is mentioned that “For backwards compatibility reasons, a new method TPython::Import has been added to expose the new functionality”. I could not find any other info. I guess that it is something planned more for ROOT7 (i.e., under development) than for ROOT6, right?

Thanks!

Cheers,
Jiri

Hi,

you can always use “TPython : : Prompt ( )” to switch between prompts.
I realise that the result is a bit misleading. I add in the loop Wim.

Cheers,
D

That tpython_test.h fails b/c it’s not valid C++; nothing to do with TPython. You can not call a C++ function in the global scope. You can either use a helper class or use a compiler extension such as the constructor attribute. (That’s not the thing, this wacko editor is taking markup: it’s dunderscored.)

The problem with math.sqrt is that it’s not a python function but a bound C function. Thus, it has no func_XYZ attributes that are needed to find things like the number of arguments etc. Granted, the code should warn rather than be silent, but without python-side reflection, the binding into C++ can not work. (Binding C functions is pointless anyway, but if you want to play more with this one, write your own python sqrt in a python module; that’ll work.)

The note about “backwards compatibility” is that Import() does similar things to LoadMacro() but the latter does not build out namespaces for modules. Because of that, I didn’t think it prudent to modify LoadMacro() and potentially break stuff, and thus simply took a new name.

I don’t know anything about ROOT7 or the future of PyROOT.

Hi @wlav,

For the future, whenever you write code just enclose it in back ticks and your underscores are left untouched. I.e. you’re referring to something called _constructor_. It’s simply markdown.

Axel

alright, __constructor__ then (dunderscore, not underscore)

1 Like

There we go :slight_smile: Thanks, Wim!

Hello Wim,

many thanks for your detailed explanation (and writing the paper), it was very helpful to understand the situation!

Indeed. I didn’t not fully realized this c++ and python difference… Solving this solved my basic problem with the compilation.

Oh, I see now the fundamental difference. Yes, better error msg would be surely helpful (e.g., TPython::Import(“array”) leads to even segmentation violation). It would be just so user friendly not to care how a function is actually implemented :slight_smile: .

The TPython::Import function for pure python non-nested modules (corresponding to one c++ namespace) works great for me. In the case of trying to import some nested modules TPython::Import(“module1.module2”) I obtain an error but this is probably another topic (I guess just not supported for the moment)…

Thanks Wim and Danilo once more again! My main problem is solved now.

Cheers,
Jiri

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.