编译几个源(主文件和头文件)并在ROOT CINT中链接它们?

时间:2017-01-04 12:33:17

标签: c++ shared-libraries executable root-framework .so

首先让我设置上下文,它是 CERN的ROOT CINT 以及 ACLiC 等。

假设我有一个名为[StructLayout(LayoutKind.Sequential, Pack=8)] public struct CommonDialogBaseParam { public UIntPtr size; [MarshalAs(UnmanagedType.ByValArray, SizeConst=36)] public byte[] reserved; public uint magic; } 的主macro和两个标题macro.cpp(包含函数的定义)和h1.cpp包含h1.h中定义的函数的声明{1}}同样我有h1.cpph2.cpp。主程序h2.hmacro.cpph1内调用这些函数。我使用以下方法成功编译了源文件:

h2

生成了三个 root [0] .L h1.cpp+ root [1] .L h2.cpp+ root [2] .L macro.cpp+ 个文件.somacro_cpp.soh1_cpp.so。我想知道如何处理它们?我如何h2_cpp.so它们以便我有类似“link”或类似的东西(某种类型的macro.out个文件)我可以执行(虽然我没有知道如何!)并实现我希望用宏实现的任何目标。

注意:如果我只是使用executable等加载所有文件,只需使用.L file_name.cpp执行主宏,那么一切正常,我有结果,但这是不是我想要的!我希望像往常一样.x macro.cpp进行编译,顺便说一句,在每个论坛中,每个人都会建议使用g++.L file_name.cpp+进行编译。我真的很想知道整个故事。因为似乎没有人在++之外解释..下一步是什么?如何处理.L file_name.cpp+等。

我是初学者,我将非常感谢一个简单而循序渐进的答案和解释。

感谢。

编辑-1:我正在使用:

g ++(Ubuntu 5.4.0-6ubuntu1~16.04.4)5.4.0 20160609

编辑-2:与ROOT相关的信息: ROOT 5.34 / 36 (v5-34-36 @ v5-34-36,dic 07 2016,23:31:51 on linuxx8664gcc) CINT / ROOT C / C ++译员版 5.18.00 ,2010年7月2日

2 个答案:

答案 0 :(得分:1)

如果要编译和链接,可以使用标准编译器而不是Cint / Aclic。 例如,假设您正在使用* nix平台,则可以使用以下示例文件:

<强> h1.h

int add_one(int a);

<强> h1.cpp

#include "h1.h"

int add_one(int a)
{
    return a+1;
}

<强> h2.h

#include <TLorentzVector.h>

TLorentzVector multiply_by_two(const TLorentzVector v);

<强> h2.cpp

#include "h2.h"

TLorentzVector multiply_by_two(const TLorentzVector v)
{
    return 2.0*v;
}

<强> macro.cpp

#include "h1.h"
#include "h2.h"

#include <TLorentzVector.h>

#include <iostream>
using std::cout;
using std::endl;

int main()
{
    int a = 0;
    TLorentzVector v;
    v.SetPtEtaPhiM(1.0, 0.0, 0.0, 0.0);
    cout<<"calling add_one on "<<a<<": "<<add_one(a)<<endl;
    cout<<"calling multiply_by_two on "<<v.Pt()<<": "<<multiply_by_two(v).Pt()<<endl;
    return 0;
}

然后你可以用

编译
g++ -c -g -Wall `root-config --cflags` h1.cpp
g++ -c -g -Wall `root-config --cflags` h2.cpp
g++ -c -g -Wall `root-config --cflags` macro.cpp

并与

相关联
g++ `root-config --glibs` h1.o h2.o macro.o

可执行文件为a.out

$ ./a.out 
calling add_one on 0: 1
calling multiply_by_two on 1: 2

您可以将这些g++命令放在脚本中,或者当您开始拥有多个文件和目录时,可以编写make文件(或cmake)。对于最后一步,请参阅此处的教程

http://www-pnp.physics.ox.ac.uk/~brisbane/Teaching/Makefiles/Tutorial_1_Makefiles_and_ROOT.pdf

注1 :使用g++的一个好处是,当某些内容无法编译时,您会收到明确的错误消息。来自Cint的错误消息可以 难以理解 - 尽管在Cling 6中这已经得到了很大的改进。

注意2 :使用标准编译器的另一个好处是,您可以轻松地将主要可执行文件与除root之外的库链接。

答案 1 :(得分:0)

这个答案主要基于user2148414的答案,但如果有人回答,则会注意到链接源(* .cpp)文件的方法存在一些问题。我的回答还涉及另一个称为 TApplication 的重要对象,它将在涉及根库的应用程序中发挥关键作用。以下链接步骤:

g++ `root-config --glibs` h1.o h2.o macro.o

可能会显示很多错误,抱怨像TWhatever这样的根对象(在user2148414的答案中TLorentzVector会显示问题)。在对该答案的评论中,人们可以找到关于包含各种物理库的讨论,这些物理库可以解决问题但是没有讨论(我也不舒服:))让我写下解决问题的命令。

这个程序是一行的,不需要编译单个文件,创建* .cpp文件和* .h文件,如that answer中所述,然后编译并链接并创建一个名为“someExecutable”的可执行文件“使用:

g++ macro.cpp h1.cpp h2.cpp `root-config --libs --cflags` -o someExecutable

或更好(一个人应该这样做)

g++ -Wall -Wextra -Werror -pedantic -std=c++14 macro.cpp h1.cpp h2.cpp `root-config --libs --cflags` -o someExecutable

这将解决我原来的答案,但为了完整起见,我想补充一些其他内容。

<强> TApplication的

我最初的动机是创建一个与“ROOT”对话的应用程序,但我不想使用ROOT shell,CINT,ACLiC等,并希望完全使用g ++。 user2148414和我的答案将解决创建应用程序的部分,但应用程序不会用于任何目的,它将运行,创建直方图绘制它们并完成所有的工作但是所有的画布最终都会关闭代码达到“return 0;”。为了保持画布打开,我们需要“TApplication”。因此,考虑user2148414main的答案,我将仅包括两行,并包含main的两个参数:

<强> macro.cpp

    #include "h1.h"
    #include "h2.h"

    #include <TLorentzVector.h>

    #include <iostream>
    using std::cout;
    using std::endl;

    int main(int argc, char* argv[])  //introduced arguments to main
    {

     // here I introduce TApplication

   TApplication* SomeApp = new TApplication("SomeApp",&argc, argv); 

        int a = 0;
        TLorentzVector v;
        v.SetPtEtaPhiM(1.0, 0.0, 0.0, 0.0);
        cout<<"calling add_one on "<<a<<": "<<add_one(a)<<endl;
        cout<<"calling multiply_by_two on "<<v.Pt()<<": "<<multiply_by_two(v).Pt()<<endl;

        //and just before returning 0
         SomeApp->Run();

        return 0;
    }