2017-01-04 21 views
0

Позвольте мне сначала установить контекст, это ROOT ЦЕРН и CINT и ACLiC и т.д.Составление нескольких исходных (главных и заголовков) файлов и их связывание в ROOT CINT?

Предположим, у меня есть главный macro имени macro.cpp и два заголовка h1.cpp (содержит определение функции) и h1.h, содержащий декларацию функции, определенной в h1.cpp Аналогичным образом у меня есть h2.cpp и h2.h. Основная программа macro.cpp вызывает эти функции внутри h1 и h2. Я была успешной компиляции исходных файлов с помощью:

root [0] .L h1.cpp+ 
    root [1] .L h2.cpp+ 
    root [2] .L macro.cpp+ 

который произвел три .so файлы macro_cpp.so, h1_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+ .. что дальше? Что делать с .so и т. Д.

Я новичок, я по-настоящему оценю простой и шаг за шагом ответ и объяснение.

Спасибо.

Edit-1: Я работаю с:

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

Edit-2: ROOT родственный информация: ROOT 5,34/36 (v5-34-36 @ v5-34-36, DIC 07 2016, 23:31:51 на linuxx8664gcc) CINT/ROOT C/C++ Интерпретатор версия 5.18.00, июль 2, 2010

+0

.so динамичны подключаемая библиотека как. dll в Windows. Короче говоря, это скомпилированный код, который может использоваться несколькими программами. Вы можете использовать команду оболочки: «ldd ./myprogram», чтобы увидеть все .so, необходимые вашей программе. – baddger964

+0

, так как вы спрашиваете «что дальше?»: После '.L macro.cpp +' вы можете выполнять функции, которые определены в этом файле, например '.L macro.cpp +; макросъемки (3,1415); '. сохраненный '.so' будет прочитан в следующий раз, когда вы сделаете' .L macro.cpp + '(без перекомпиляции макросов, которые уже скомпилированы). или вы можете просто загрузить ранее скомпилированные '.so' файлы с помощью' gSystem-> Load ("macro_C.so"); '. – pseyfert

+0

@pseyfert это замечательно. – quanta

ответ

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.ч

#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++ команд в сценарии или, когда вы начинаете с несколькими файлами и каталогами, вы можете написать свой макияж файл (или cmake). Для этого последнего шага, смотрите, например, учебник здесь

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

Примечание 1: одно преимущество использования g++ является то, что вы получите четкие сообщения об ошибках, когда что-то не компилируется. Сообщения об ошибках от Cint могут быть сложными для понимания - хотя это очень улучшено в корне 6 с помощью Cling.

Примечание 2: еще одно преимущество использования стандартного компилятора заключается в том, что вы сможете легко связать свой основной исполняемый файл с библиотеками, отличными от root.

+0

Я согласен с использованием g ++, а не cint/aclic. На самом деле я знаю, как связать обычные источники C++, которые не связаны с корневыми библиотеками, из вашего ответа теперь я знаю, как связывать библиотеки корней. Я попробую и вернусь. Проблема, однако, с «main» заключается в том, что я не могу кормить имя файла ROOT и другие параметры во время самого выполнения, так как «main» не принимает таких аргументов, я думаю. Предположим, что 'macro' похож на' void macro (TString filename, Int_t nbin) ', как это изменит ситуацию? – quanta

+0

Я могу, конечно, изменить макрос на 'main', как вы это делали, а затем' std :: cin >> имя_файла' и т. Д. Это тоже будет работать, но просить иначе только ради знания. – quanta

+0

команда связывания 'g ++' root-config -glibs' h1.o h2.o macro.o' создает много ошибок (возможно, что-то связано с TLorentzVector и include include path), которые я не могу разместить в одном комментарии поэтому публикация в нескольких (следующих) комментариях: – quanta

0

Этот ответ основан главным образом на ответе user2148414, но если следовать за ответом, то заметите, что были некоторые проблемы с методом связывания файлов источника (* .cpp). Мой ответ также касается другого важного объекта, называемого TApplication, который будет играть решающую роль в таких приложениях, в которых используются библиотеки корней. Следующий этап связывания:

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

вероятно покажет много ошибок, жалующихся корневых объектов, таких как TWhatever (в ответ user2148414 «s 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 оболочки, CINT, ACLiC и т.д., и хотел работать полностью с г ++. user2148414 и мой ответ разрешит часть создания приложения, но приложение не будет служить никакой цели, оно запустится, создаст гистограммы, нарисует их и сделает все, но все полотна закроются в конце, когда код достигнет " return 0; ". Чтобы сохранить холсты открытыми, нам понадобится «TApplication». Таким образом, рассмотрим main из ответа user2148414 «s, я буду включать только еще две линии, и включают в себя два аргумента к 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; 
    }