I need help making a shared object (edit: and executing them)

Hey Guys,

I’ve been trying to read up on as many resources as possible, but now its seems once again I’m at an impasse
I want to compile the following file into an .so

//structs.hpp
struct foo
{
void setD(double _d) { d = _d;}
double getD() {return d;}
private:
double d;
};

I was attempting to replacate section 9.4 root.cern.ch/root/htmldoc/guide … Cling.html here, but loading in files with .L structs structs.C+ or .C++ didn’t generate any .so files.

and yes, i copied structs.hpp to structs.C++ just to be sure.

What am I missing?
Thanks in advance

Hi,

this is odd: aclic works in ROOT6 as in ROOT5.
How did you install root? Do you see any error/warning?
Do you see any indication of some issue if you raise the debug level, say to (gDebug=1,2,3)

Danilo

Hi Danilo, this seems to have been a misunderstanding on my part.

Most of my tests were running on vamilla cling, and i didnt spend the extra time confirming if my results would be the same under the ROOT environment

Ill need to come back to confirm for sure, but would it be safe to assume that the .so files generated by root6 would work in vamilla cling?

Hi,

I suspected you were using cling only but I wrongly interpreted the pointer to the ROOT documentation: I have my share in the generation of misunderstanding :slight_smile:
I am afraid cling is not enough to generate libraries with the “.L macro.C+” magic: this is ACLiC, a feature of ROOT, which generates dictionaries for all classes in the file and compiles them together with the code in a shared library.

Cheers,
Danilo

Ok, So I switched back to the root 6.04.06 (vs vanilla cling)

I tried loading in my header, and as expected it created a .so file!
When loading in the .so file into the interpreter, the root/cling interpreter seems to understand everything that should have been in there (which is great).

Now When i’m using the the included headers for the Interpreter for root, I seem to get no dice with Interpreter::loadFile(“path/to/the/.so”);

my program still works if I include the headers, but now, I’m at bit of a loss, especially since the 2nd parameter to Intepreter::loadFile() is a boolean which toggles whether it acccets so files (default true)…

As always, just let me know if im not providing enough informtion,
Thanks

Hi,

sorry I do not get what you are trying to do

Could you clarify?
In addition: do you need to use cling standalone and no ROOT?

[quote=“dpiparo”]Hi,

sorry I do not get what you are trying to do

Could you clarify?
In addition: do you need to use cling standalone and no ROOT?[/quote]

I thought I needed stand-alone root, then I realized that it wasn’t necessary

I’m going to give you as much information as I can to help you reproduce my problem

here is my source file

#include <iostream>
#include <string>

#include <cling/Interpreter/Interpreter.h>

static const std::string PATH_TO_STRUCTS = "/home/d4nf/clingTest/structs.C";
static const std::string PATH_TO_STRUCTS_SO = "/home/d4nf/clingTest/structs_C.so";
static const std::string PATH_TO_LLVM {"/home/d4nf/Downloads/Root-prefix/etc/cling"};
static const char * clingArgs[] = {"", "-std=c++11"};
int main()

{
    cling::Interpreter inter(2, clingArgs, PATH_TO_LLVM.c_str());
    inter.loadFile(PATH_TO_STRUCTS_SO.c_str());
    inter.process("std::cout << \"test Hello \";\n"
                "foo bar;\n"
                "bar.getD();\n");

}

Here is my structs.C file

#include <iostream> #include <string> struct foo { void setD(double _d) { d = _d;} double getD() {return d;} private: double d; };

Here is my CMakeLists.txt file

    cmake_minimum_required(VERSION 3.0)

set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")


set (ROOT_DIR /home/d4nf/Downloads/Root-prefix/)

set (ROOT_INCLUDES
${ROOT_DIR}/etc
)
include_directories(${ROOT_INCLUDES})

set (ROOT_LIBS
${ROOT_DIR}/lib/libCore.so
${ROOT_DIR}/lib/libCling.so
${ROOT_DIR}/lib/libRIO.so
${ROOT_DIR}/lib/libThread.so
${ROOT_DIR}/lib/libRint.so
${ROOT_DIR}/lib/libMathCore.so
)
add_executable(tcling main.cpp)
target_link_libraries(tcling ${ROOT_LIBS})

When structs.C is compiled in, this is the root/cling output

[quote]./tcling
test Hello[/quote]

When structs_C.so is compiled in, this is the root.cling output

Hi,

this post started with the wish of creating a shared library.
Can you confirm that your goal is to embed cling in an application and execute some code, namely with something like:

    cling::Interpreter inter(2, clingArgs, PATH_TO_LLVM.c_str());
    inter.loadFile(PATH_TO_STRUCTS_SO.c_str());
    inter.process("std::cout << \"test Hello \";\n"
                "foo bar;\n"
                "bar.getD();\n");

?

[quote=“dpiparo”]Hi,

this post started with the wish of creating a shared library.
Can you confirm that your goal is to embed cling in an application and execute some code, namely with something like:

    cling::Interpreter inter(2, clingArgs, PATH_TO_LLVM.c_str());
    inter.loadFile(PATH_TO_STRUCTS_SO.c_str());
    inter.process("std::cout << \"test Hello \";\n"
                "foo bar;\n"
                "bar.getD();\n");

?[/quote]
Yes, sorry for not being clear. I’m just getting weary of making a new thread for every problem im facing.
Thanks

Hi,

When you load the library, nobody is #including . A simple

interp.declare("#include ");

before using cout will do.

Cheers, Axel.

Hey Axel, thanks for responding

that still doesn’t resolve the issue with cling not finding foo…

//structs.C
struct foo
{
void setD(double _d) { d = _d;}
double getD() {return d;}
private:
double d;
};

[code]#include
#include

#include <cling/Interpreter/Interpreter.h>

static const std::string PATH_TO_STRUCTS = “/home/d4nf/clingTest/structs.C”;
static const std::string PATH_TO_STRUCTS_SO = “/home/d4nf/clingTest/structs_C.so”;
static const std::string PATH_TO_LLVM {"/home/d4nf/Downloads/Root-prefix/etc/cling"};
static const char * clingArgs[] = {"", “-std=c++11”};
int main()

{
cling::Interpreter inter(2, clingArgs, PATH_TO_LLVM.c_str());
inter.loadFile(PATH_TO_STRUCTS_SO.c_str());
inter.declare("#include ");
inter.process("std::cout << "test Hello “;\n”
“foo bar;\n”
“std::cout << bar.getD() << std::endl;\n”
“bar.setD(4.214743);\n”
“std::cout << bar.getD() << std::endl;\n”);
[/code]

loading the (recompiled structs.C file with structs.C++ on root/aclic)

[quote=“The Error messages”]./tcling
input_line_4:3:1: error: use of undeclared identifier ‘foo’; did you mean ‘for’?
foo bar;
^~~
for
input_line_4:3:5: error: expected ‘(’ after 'for’
foo bar;
^
input_line_4:4:14: error: use of undeclared identifier 'bar’
std::cout << bar.getD() << std::endl;
^
input_line_4:5:1: error: use of undeclared identifier 'bar’
bar.setD(4.214743);
^
input_line_4:6:14: error: use of undeclared identifier 'bar’
std::cout << bar.getD() << std::endl;
[/quote]

This is the output when I compiled the structs.so file

[quote]
root [0] .L /home/d4nf/clingTest/structs.C++
Info in TUnixSystem::ACLiC: creating shared library /home/d4nf/clingTest/structs_C.so
Warning in : Failed to generate the dependency file for /home/d4nf/clingTest/structs_C.so[/quote]

perhaps failing to “generate the dependency file” is the cause of my troubles? If so, what can I do to resolve this?

Thanks

Hi,

it seems that the header file (in your case structs.C) containing “foo” is missing. The interpreter does not know about foo unless you include it.

Cheers,
D

Hi,

I’m lost :slight_smile: You cannot use ROOT to generate the shared library, and then load it into cling. Well you can - but it doesn’t make a lot of sense.

If you want to use foo in cling then you need to #include its header. If you use ROOT, .L foo.C+ will trigger that upon loading the library. But that’s ROOT, and ROOT and cling are not the same thing.

Cheers, Axel.

[quote=“Axel”]Hi,

I’m lost :slight_smile: You cannot use ROOT to generate the shared library, and then load it into cling. Well you can - but it doesn’t make a lot of sense.

If you want to use foo in cling then you need to #include its header. If you use ROOT, .L foo.C+ will trigger that upon loading the library. But that’s ROOT, and ROOT and cling are not the same thing.

Cheers, Axel.[/quote]

Well, that’s a bummer. I was hoping that I could save some runtime by providing some precompiled byte-code, so to speak, to the interpreter. LuaJit has this feature, and I was hoping cling did too.

Since it seems, at least according to you, that cling doesn’t contain this feature, would you know if any support for precmpiling files in cling is planned in the near or long term future?

Thanks again,
I’ll be marking this thread as solved

Hi,

You can create a PCH. ROOT does it for its core files. Just provide it as two extra elements “-include-pch”, “myPCHFile.pch” in the argv to the cling constructor.

Cheers, Axel.