Using libjansson in ROOT CINT

Hi all.

I’m trying to use libjansson in ROOT. libjansson is a JSON library for C.

From the CINT, loading the library “seems” to work. But, I can’t use any of the functions.

root [0] gSystem->Load("/usr/local/lib/libjansson.so")
(int)0

root [2] gSystem->AddIncludePath("/usr/local/include/jansson.h")
root [3] gSystem->AddIncludePath("/usr/local/include/")
root [4] json_t *obj
Error: Symbol json_t is not defined in current scope  (tmpfile):1:
Error: Symbol obj is not defined in current scope  (tmpfile):1:
(const int)0

root [5] json_pack("{s:s}","hello","world")
Error: Function json_pack("{s:s}","hello","world") is not defined in current scope  (tmpfile):1:

any help is appreciated!
Adam

I also tried to compile a test program


root [2] .x testfunction.cc++
Info in <TUnixSystem::ACLiC>: creating shared library /Users/adam/./testfunction_cc.so
Warning in <ACLiC>: Failed to generate the dependency file for /Users/adam/./testfunction_cc.so
In file included from /var/tmp/tmp.0.pvz9ZE_cint.cxx:1:
/var/tmp//rootcint_Npb6NS.h:3:30: error: /usr/local/include: No such file or directory
Error: external preprocessing failed. :0:
!!!Removing /Users/adam/testfunction_cc_ACLiC_dict.cxx /Users/adam/testfunction_cc_ACLiC_dict.h !!!
Error: /Users/adam/softwareDev/root/v5.28.00a/bin/rootcint: error loading headers...
Error in <ACLiC>: Dictionary generation failed!
Info in <ACLiC>: Invoking compiler to check macro's validity
i686-apple-darwin10-g++-4.2.1: /usr/local/include: linker input file unused because linking not done
Info in <ACLiC>: The compiler has not found any problem with your macro.
	Probably your macro uses something rootcint can't parse.
	Check http://root.cern.ch/root/Cint.phtml?limitations for Cint's limitations.
Error: Function testfunction() is not defined in current scope  :-1:
*** Interpreter error recovered ***

where testfunction.cc is

#include "jansson.h"
#include <iostream>

void testfunction(void)
{

  json_t *obj = json_pack("{s:s}","hello","world");

  char * buf = json_dumps(obj, JSON_INDENT(2));
  std::cout << buf << std::endl;

}

Okay! This works.


root[2] gInterpreter->AddIncludePath("/usr/local/include")
root [3] gSystem->Load("/usr/local/lib/libjansson.so")
(int)0
root [4] .L testfunction.cc++
Info in <TUnixSystem::ACLiC>: creating shared library /Users/adam/./testfunction_cc.so
root [5] testfunction()
{
  "hello": "world"
}

But, is there any way to get the json_t types available in the cint?

json_t *obj = json_pack("{s:s}","hello","world")

[quote]But, is there any way to get the json_t types available in the cint?[/quote]Yes. You need to generate a dictionary for this type. For example, this should do:[code]gInterpreter->AddIncludePath("/usr/local/include");
gSystem->Load("/usr/local/lib/libjansson.so");
.L /usr/local/include/jansson.h+[code]

Cheers,
Philippe.

Hi Philippe… this worked, but I’m still missing a few things.

  1. The jansson.h file includes a number of macros, how would I tell ACLiC about these? Also, how would I do this exactly with a LinkDef file? (would I need to just make a #pragma entry in the LinkDef file for every #define found in jansson.h?)

  2. The jansson.h file has the following line:

#define JANSSON_VERSION_HEX  ((JANSSON_MAJOR_VERSION << 16) |  \
                              (JANSSON_MINOR_VERSION << 8)  |  \
                              (JANSSON_MICRO_VERSION << 0))

rootcint doesn’t like this.

Error: unexpected character in expression 0))  /usr/local/include/jansson.h:35:
Error: unexpected character in expression 0))  /usr/local/include/jansson.h:35:
Warning: Error occurred during reading source files
Warning: Error occurred during dictionary source generation

If I edit jansson.h and put it all into a single line, it doesn’t complain. NOTE: ACLiC did not complain about this.

  1. My ultimate goal with all of this is the following. I have a module in our data analysis software framework which builds a separate library (let’s call it mylib.so). This library depends on libjansson (and libcurl). I want it to be automatic for my collaborators to access the libjansson stuff, if possible. Or, at least very easily.
    There are two ways.
    A) provide them with a .h file (a LinkDef.h??) that they would call from the CINT which would make the necessary calls to gInterpreter, AddIncludePath and then .L /usr/local/include.jansson.h. One problem with this is that the location of jansson.h could vary on each system… but that’s a pretty trivial problem to overcome.

    B) My current attempts are to put the janson.h file into my LinkDef file and link this into mylib. This is the ideal solution for me.

I have a LinkDef file like this.

#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ nestedclasses;

#pragma link C++ defined_in jansson.h;
#pragma link C++ class MyClass+;
#endif

and my rootcint call looks like:

rootcint -f mylib/mylib_Dict.C -c -Iinclude   -I/usr/local/include  mylib/MyClass.h /usr/local/include/jansson.h mylib/mylib_LinkDef.h 

When a user loads mylib.so, they automatically get the libjansson functionality at the CINT. I just got this option to work, but its missing the macros, which I would have to presumably add by hand. BUT, it also required me to edit the jansson.h file so that rootcint doesn’t complain!

Please let me know what you think. Getting the macros to work in ACLiC would be helpful, and I would appreciate it if you could tell me if my current approach is reasonable.

thanks,
Adam Cox

[quote]1. The jansson.h file includes a number of macros, how would I tell ACLiC about these? Also, how would I do this exactly with a LinkDef file? (would I need to just make a #pragma entry in the LinkDef file for every #define found in jansson.h?)[/quote]You can use the pragma:#pragma link C++ global JANSSON_VERSION_HEXNote that you can even use this to direct ACLiC (by passing it a file that contain that line surrounded with #ifndef MAKECINT and including the file containing the definition of the macro)

Cheers,
Philippe.