私は、完全に独立して実行できる2つの関数を持つC++プログラムを作成しています。だから私はそれらを2つのプログラムに分割したい。C++プログラムをモジュールに分割する方法
問題は、両方とも同じ機能セット(拡張または変更可能)に依存していることです。私がやりたいことは、両方のプログラムのヘッダーとしてこの機能セットを含めることです。何かを変更するたびにコピー/貼り付けをしなくてもいいです(機能の重複も嫌いです)。
私は愚かな質問があることは知っていますが、私はその問題に関する文書を見つけることができませんでした。
コードが必要な場合は質問して投稿します。
ありがとうございます!
EDIT:
追加コード:
独立して実行できる機能はmake_video()とdelete_videoは() 行ってから、これは遠く離れていることを念頭に置いていてください。
#include <sys/types.h>
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string>
#include <cstring>
#include <dirent.h>
#include <vector>
#include <time.h>
#include <csignal>
#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>
#include <mysql/mysql.h>
#include <mysql_connection.h>
#include <mysql_driver.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
struct config_t{
std::string sql_host; //mysql host
std::string sql_user; //mysql user
std::string sql_pass; //mysql password
std::string sql_db; //zoneminder database name
std::string sql_ev_zm; //zoneminder events table
std::string sql_ev_vid; //video events table
std::string sql_ev_videxp; //video events expiration table
std::string sql_mon; //zm monitors table
std::string dir_ev; //Zoneminder events directory
std::string dir_vid; //manager videos directory
std::string dir_ram; //Ramfs mount directory
std::string ram_size; //ramfs size
};
int is_dir(const char *pathname){
struct stat info;
if(stat(pathname, &info) != 0)
return -1;
else if(info.st_mode & S_IFDIR) // S_ISDIR() doesn't exist on my windows
return 1;
else
return 0;
}
// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
}
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
// trim from start (copying)
static inline std::string ltrimmed(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrimmed(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trimmed(std::string s) {
trim(s);
return s;
}
bool DirectoryExists (const char* path){
if(path == NULL)return false;
DIR *d;
d = opendir(path);
if (d){
closedir(d);
return true;
}
return false;
}
std::ifstream::pos_type filesize(const char* filename){
std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
return in.tellg();
}
bool mount_ramfs(config_t *conf){
return false;
}
bool make_video(config_t *conf, std::string path = "", int depth = 0){
try{
sql::mysql::MySQL_Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
driver = sql::mysql::get_mysql_driver_instance();
con = driver->connect(conf->sql_host, conf->sql_user, conf->sql_pass);
stmt = con->createStatement();
stmt->execute("USE " + conf->sql_db);
std::string query = "SELECT Id, MonitorId, StartTime, EndTime, Length, Frames FROM " + conf->sql_ev_zm + " WHERE EndTime IS NOT NULL LIMIT 10"; //select a bunch of events for processing, EndTime NOT NULL means that the event is complete and not corrupted
//syslog (LOG_DEBUG, "Mysql Query: %s", query.c_str());
res = stmt->executeQuery(query);
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime < NOW() - INTERVAL 1 DAY ORDER BY Id ASC LIMIT 1
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime LIKE "%2015-11-18%" and MonitorId = 56
// conf.dir_ev + "/" + MonitorId + "/" + todir(StartTime)
while (res->next()) {
int id = res->getInt("Id");
int monitor = res->getInt("MonitorId");
std::string start_time = res->getString("StartTime");
std::string end_time = res->getString("EndTime");
int lenght = res->getInt("Length");
int frames = res->getInt("Frames");
//Get event directory form table data; the dir structure is id/YY/MM/DD/HH/mm/ss/
char sttm[60] = {};
std::strcpy(sttm, start_time.c_str());
char * tkn = (char*)malloc(60);
std::stringstream pathSS;
pathSS << conf->dir_ev << '/' << id << '/'; //prepare the path
tkn = std::strtok (sttm," -:"); //here we tokenize the StartTime field to match the source directory structure
if (tkn != NULL) {
pathSS << tkn[2] << tkn[3] << '/';
tkn = std::strtok (NULL, " -:");
}
while (tkn != NULL) {
pathSS << tkn << '/';
tkn = std::strtok (NULL, " -:");
}
std::string src = pathSS.str();
pathSS.clear();
pathSS << conf->dir_vid << '/' << id << '/'; //prepare the path
std::string dest = pathSS.str();
pathSS.clear();
tkn = std::strtok (sttm," -:"); //here we tokenize the StartTime field to make the destinantion and filename
while (tkn != NULL) {
pathSS << tkn << '_'; //sadly this will always lead to "_.mp4" but its not that bad or important
tkn = std::strtok (NULL, " -:");
}
pathSS << ".mp4";
std::string fname = pathSS.str();
pathSS.clear();
//do event video and
/*std::string cmd = "mkdir -p " + conf->dir_vid + path;
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());
cmd = "tar -zcf " + conf->dir_vid + path + "/" + dirlist[i] +".tar.gz " + conf->dir_ev + path + "/" + dirlist[i];
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());
cmd = "rm -rf " + conf->dir_ev + src + "*";
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());*/
try{
//insert new row in videos table
pathSS << "INSERT INTO " << conf->sql_ev_vid << " (startTime, endTime, monitor, filename) VALUES (\'" << start_time << "\', \'" << end_time << "\', " << monitor << ",\'" << dest << fname << "\')";
stmt->execute(pathSS.str());
pathSS.clear();
//delete non existing event
pathSS << "DELETE FROM " << conf->sql_ev_zm << " WHERE Id = " << id;
stmt->execute(pathSS.str());
pathSS.clear();
}
catch(sql::SQLException &e){
syslog (LOG_ERR, "Mysql Exception: %s, ERRNO %i, MySQL State: %s", e.what(), e.getErrorCode(), std::string(e.getSQLState()).c_str());
exit(EXIT_FAILURE);
}
}
delete res;
delete stmt;
delete con;
}
catch(sql::SQLException &e){
syslog (LOG_ERR, "Mysql Exception: %s, ERRNO %i, MySQL State: %s", e.what(), e.getErrorCode(), std::string(e.getSQLState()).c_str());
exit(EXIT_FAILURE);
}
return true;
}
bool delete_video(config_t *conf){
try{
sql::mysql::MySQL_Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
sql::ResultSet *subres;
driver = sql::mysql::get_mysql_driver_instance();
con = driver->connect(conf->sql_host, conf->sql_user, conf->sql_pass);
stmt = con->createStatement();
stmt->execute("USE " + conf->sql_db);
std::string query = "SELECT monitor, recording_days FROM " + conf->sql_ev_videxp + " WHERE 1";
//syslog (LOG_DEBUG, "Mysql Query: %s", query.c_str());
res = stmt->executeQuery(query);
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime < NOW() - INTERVAL 1 DAY ORDER BY Id ASC LIMIT 1
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime LIKE "%2015-11-18%" and MonitorId = 56
// conf.dir_ev + "/" + MonitorId + "/" + todir(StartTime)
while (res->next()) {
int id = res->getInt("Id");
int r_days = res->getInt("recording_days");
//syslog (LOG_DEBUG, "Id: %i, Recording Days: %i", id, r_days);
std::stringstream subQuerySS;
subQuerySS << "SELECT id, file FROM " << conf->sql_ev_vid << " WHERE date < NOW() - INTERVAL " << r_days << " DAY AND monitor = " << id;
std::string subQuery = subQuerySS.str();
subQuerySS.clear();
//syslog (LOG_DEBUG, "Mysql Query: %s", subQuery.c_str());
subres = stmt->executeQuery(subQuery);
while (subres->next()) {
int subid = subres->getInt("id");
std::string file = subres->getString("file");
std::string cmd = "rm -f " + file;
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());
std::stringstream delQuerySS;
delQuerySS << "DELETE FROM " << conf->sql_ev_vid << " WHERE id = " << subid;
std::string delQuery = delQuerySS.str();
delQuerySS.clear();
syslog (LOG_DEBUG, "Mysql Query: %s", delQuery.c_str());
stmt->execute(delQuery);
}
}
delete res;
delete subres;
delete stmt;
delete con;
}
catch(sql::SQLException &e){
syslog (LOG_ERR, "Mysql Exception: %s, ERRNO %i, MySQL State: %s", e.what(), e.getErrorCode(), std::string(e.getSQLState()).c_str());
exit(EXIT_FAILURE);
}
return true;
}
void signalHandler(int signum){
syslog (LOG_NOTICE, "signal received (%i)", signum);
closelog();
exit(signum);
}
int main(void) {
/* Our process ID and Session ID */
pid_t pid, sid;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then
we can exit the parent process. */
if (pid > 0) {
std::ofstream pid_file;
pid_file.open("evmanager.pid", std::ofstream::trunc);
if(pid_file.is_open()){
pid_file << pid;
pid_file.close();
}
exit(EXIT_SUCCESS);
}
/* Change the file mode mask */
umask(0);
setlogmask (LOG_UPTO (LOG_DEBUG));
openlog ("dt_event_manager", LOG_PID, LOG_DAEMON);
syslog (LOG_NOTICE, "Program started by User %d", getuid());
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
syslog (LOG_ERR, "SID Creation Failed");
exit(EXIT_FAILURE);
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
syslog (LOG_ERR, "Failed while Changing directory to /");
exit(EXIT_FAILURE);
}
/* Read Initial Configuration */
std::ifstream conf_file;
std::string line;
config_t conf;
conf_file.open("/etc/zm/evmanager.conf");
if(conf_file.is_open()){
while(std::getline(conf_file, line)){
if(line[0] == '#')continue;
std::istringstream is_line(line);
std::string key;
if(std::getline(is_line, key, '=')){
std::string value;
if(std::getline(is_line, value)){
trim(key);
trim(value);
if(key == "sql_host")conf.sql_host = value; //mysql host
else if(key == "sql_user")conf.sql_user = value; //mysql user
else if(key == "sql_pass")conf.sql_pass = value; //mysql password
else if(key == "sql_db")conf.sql_db = value; //zoneminder database name
else if(key == "sql_ev_zm")conf.sql_ev_zm = value; //zoneminder events table
else if(key == "sql_ev_vid")conf.sql_ev_vid = value; //video events table
else if(key == "sql_ev_videxp")conf.sql_ev_videxp = value; //Zoneminder videos expiration directory
else if(key == "sql_mon")conf.sql_mon = value; //Zoneminder Monitors directory
else if(key == "dir_ev")conf.dir_ev = value; //Zoneminder events directory
else if(key == "dir_vid")conf.dir_vid = value; //Manager Videos directory
else if(key == "dir_ram")conf.dir_ram = value; //Ramfs mount dir
else if(key == "ram_size")conf.ram_size = value; //Ramfs size
else{
syslog (LOG_ERR, "Bad config readout");
exit(EXIT_FAILURE);
}
}
}
}
}
else{
syslog (LOG_ERR, "Failed to open configuration file");
exit(EXIT_FAILURE);
}
/* Close out the standard file descriptors */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* Daemon-specific initialization goes here */
/* The Big Loop */
signal(SIGINT, signalHandler);
syslog (LOG_INFO, "Daemon Started");
while (1) {
make_video();
delete_video();
sleep(10); /* wait 10 seconds */
}
exit(EXIT_SUCCESS);
}
起動パラメータを持つプログラムを1つ作成し、それを2回起動しますか? – guiguiblitz
それは決して考えなかった、すばらしかった!しかし、これはLinuxのサービスなので、私は親プロセスを終了し、同じパラメータで子供を起動する方法を知らない、病気はいくつかのテストを行う必要があります。 – Arheisel
コードを送信してください、今は不明です。 –