How to make char array available in multiple .cpp files? - c++

I have a working program which must be split into multiple parts, for edition purposes. This program is needed to keep user login info in char arrays to be able to connect to SQL, and this connection info is used many times in parts of the program that will end up in separated .cpp files, which will compile in a single program.
The problem is that if they are declared in just one file, they will be missing in the rest, and if they are declared in all of them, there will be duplicated definitions.
So, to make a concrete and simple example, if I have the following code:
#include <mysql++/mysql++.h>
#include <iostream>
using namespace std;
using namespace mysqlpp;
char server[] = "localhost";
char user[] = "root";
char pass[] = "xxxxxxx";
char db[] = "prog";
void function()
{
Connection con;
con.connect("", server, user, pass);
con.select_db(db);
//action1...;
}
void separated_function()
{
Connection con;
con.connect("", server, user, pass);
con.select_db(db);
//action2...;
}
int
main( int argc, char *argv[] )
{
cout << "INICIO\n";
function();
separated_function();
//something else with the mentioned variables...;
cout << "FIN\n";
return 0;
}
How can it be split correctly, to have function(), another_function() and main() in separated .cpp files,and make server, user, pass and db avaliable to all of them.
I know there must be many ways, but any working one is good enough, since I'm not getting any results so far.
NOTE: This question is not about how to use the variables with MySQL, but how to split the program correctly.

You want to use extern in the seperated source files, or in a common header that is included in the seperated source files. You will define them in one (and only one) cpp file. Here is an example:
main.h
void function();
void seperated_function();
namespace myGlobals {
extern char server[];
extern char user[];
extern char pass[];
extern char db[];
}
main.cpp
#include <iostream>
#include "main.h"
namespace myGlobals {
char server[] = "localhost";
char user[] = "root";
char pass[] = "xxxxxxx";
char db[] = "prog";
}
int main(int argc, char *argv[]) {
std::cout << "main.cpp\n";
std::cout << myGlobals::server << "\n";
std::cout << myGlobals::user << "\n";
std::cout << myGlobals::pass << "\n";
std::cout << myGlobals::db << "\n\n";
function();
seperated_function();
return 0;
}
function.cpp
#include <iostream>
#include "main.h"
void function() {
std::cout << "function.cpp\n";
std::cout << myGlobals::server << "\n";
std::cout << myGlobals::user << "\n";
std::cout << myGlobals::pass << "\n";
std::cout << myGlobals::db << "\n\n";
}
seperated_function.cpp
#include <iostream>
#include "main.h"
void seperated_function() {
std::cout << "seperated function.cpp\n";
std::cout << myGlobals::server << "\n";
std::cout << myGlobals::user << "\n";
std::cout << myGlobals::pass << "\n";
std::cout << myGlobals::db << "\n\n";
}
The namespace myGlobals is not required, but if I am going to use global variables I at least like to put them in their own namespace.

Related

Parsing Pointers & Using them between classes [C++]

So I'm fairly new to C++ and I've only started to code into it a few weeks or so. I've been facing a problem that I could not manage to fix. Every time I learned a new programming language, I give myself the challenge to make a little program (not too complex) which groups everything I've learned about that language (functions, classes, arrays, pointers and so on) so I can get a good understand of how actually coding in that language is.
So I decided to make my first C++ program called Chek to check the current MBPS (connection speed) every hour, minutes, or second that the user can input. Like all of my programs, I use a structure that I always use that I discovered while coding in Java (Since I know Java fluidly). Which looks like this:
I've also added a comment of where my issue is in the whole in Lib/Arguments.cpp.
Let's say I was to code Chek in Java. I would do my structure like:
Chek or Main class
|- Core
|- Core (The class that handles initiating each core's libraries)
|- Arguments (For parsing, checking and understand arguments)
|- Broadcast (To print to screen and so on)
|- Network (For network interaction)
|- Logs (To save to file logs)
Then the rest ...
Each Core's lib is handled by the Core, like... To call the Broadcast methods, I would do:
Main().getCore().getBroadcast().BroadcastMsg("Hello!");
So I can access all libraries, methods, and variables without creating deadlocks or any infinite importing loops.
My problem is I'm trying to do this in C++ but it's not working! I've tried a lot of stuff, changing pointers to Object and so on but it doesn't work so I need help!
Here's my code (I'm also using Visual Studio):
Chek.cpp:
#include "pch.h"
#include "Main.h"
#include "Core.h"
#include <iostream>
int main(int argc, char *argv[])
{
Core* Ptr = new Core;
Main OBJ; Main* Ptr2; Ptr2 = &OBJ;
std::cout << "Generated PTR's!" << std::endl;
std::cout << "Core PTR -> " << Ptr << std::endl;
std::cout << "Main PTR -> " << Ptr2 << std::endl << std::endl;
Ptr2->SetCrPtr(Ptr);
Ptr2->loadChek(argv);
}
Main/Main.h:
#pragma once
#ifndef __MAIN_H
#define __MAIN_H
class Core;
class Main
{
public:
Main();
private:
Core* CrPtr;
public:
void loadChek(char *arguments[]);
void SetCrPtr(Core* Ptr);
Core* getCrPtr();
};
#endif
Main/Main.cpp:
#include "pch.h"
#include "Main.h"
#include "Core.h"
#include "Arguments.h"
#include "Broadcast.h"
#include <iostream>
using namespace std;
Main::Main() : CrPtr() {};
void Main::SetCrPtr(Core* Ptr)
{
std::cout << "[Main] Setting CrPtr to " << Ptr << std::endl;
this->CrPtr = Ptr;
}
Core* Main::getCrPtr()
{
return this->CrPtr;
}
void Main::loadChek(char *arguments[])
{
char *allArguments[sizeof(arguments)];
this->CrPtr->SetMnPtr(this);
this->CrPtr->setArguments();
this->CrPtr->setBroadcast();
this->CrPtr->getBroadcast()->Log(1, "Loading arguments ...\n");
this->CrPtr->getArguments()->parseArguments(arguments, allArguments);
}
Core/Core.h:
#pragma once
#ifndef __CLASS_H
#define __CLASS_H
#include "Arguments.h"
#include "Broadcast.h"
class Main;
class Core
{
public:
Core();
private:
Main* MnPtr;
Arguments* ArgPtr;
Broadcast* BrdPtr;
public:
Arguments* getArguments();
void setArguments();
Broadcast* getBroadcast();
void setBroadcast();
void SetMnPtr(Main* Ptr);
};
#endif
Core/Core.cpp:
#include "pch.h"
#include "Core.h"
#include "Main.h"
Core::Core() : MnPtr() {}
void Core::SetMnPtr(Main* Ptr)
{
std::cout << "[Core] Setting MnPtr to " << Ptr << std::endl;
this->MnPtr = Ptr;
}
void Core::setArguments()
{
this->ArgPtr = new Arguments;
std::cout << "[Core] Setting Argument's MnPtr to " << this->MnPtr << std::endl;
this->ArgPtr->SetMnPtr(this->MnPtr);
}
void Core::setBroadcast()
{
this->BrdPtr = new Broadcast;
std::cout << "[Core] Setting Broadcast's MnPtr to " << this->MnPtr << std::endl;
this->BrdPtr->SetMnPtr(this->MnPtr);
}
Arguments* Core::getArguments()
{
return ArgPtr;
}
Broadcast* Core::getBroadcast()
{
return BrdPtr;
}
Lib/Arguments.h:
#pragma once
class Main;
class Arguments
{
public:
Arguments();
private:
Main* MnPtr;
public:
void parseArguments(char *arguments[], char *argumentsElements[]);
void SetMnPtr(Main* Ptr);
Main* GetMnPtr();
};
Lib/Arguments.cpp:
#include "pch.h"
#include "Arguments.h"
#include <iostream>
Arguments::Arguments() : MnPtr() {}
void Arguments::SetMnPtr(Main* Ptr)
{
std::cout << "[Arguments] Setting MnPtr to " << Ptr << std::endl;
this->MnPtr = Ptr;
}
Main* Arguments::GetMnPtr()
{
return this->MnPtr;
}
void Arguments::parseArguments(char *arguments[], char *argumentsElements[])
{
try {
if (sizeof(arguments) == 1 || sizeof(arguments) > 4) throw 1;
}
catch (int errorCode) {
if (errorCode == 1) std::cout << "Wrong usage!\n\nUsage: chek.exe <timeout-in-miliseconds> <log-file-path>\nExample: chek.exe 10000 saturday_log_file.txt\n";
}
std::cout << "Size -> " << sizeof(arguments) << std::endl;
for(int i=0; i<sizeof(arguments); i++)
{
// The error is produced here, for some reason after MnPtr,
// nothing is recognised. Like getCrPtr()... has never been declared?
this->MnPtr->getCrPtr()->getBroadcast()->(1, "Works!");
}
}
Lib/Broadcast.h:
#pragma once
#include <iostream>
#include "Main.h"
class Broadcast
{
public:
Broadcast();
private:
Main* MnPtr;
public:
void Log(unsigned int statusLevel, std::string message);
void SetMnPtr(Main* Ptr);
};
Lib/Broadcast.cpp:
#include "pch.h"
#include "Broadcast.h"
#include <iostream>
#include <string>
using namespace std;
Broadcast::Broadcast() : MnPtr() {}
void Broadcast::SetMnPtr(Main* Ptr)
{
std::cout << "[Broadcast] Setting MnPtr to " << Ptr << std::endl;
this->MnPtr = Ptr;
}
void Broadcast::Log(unsigned int statusLevel, string message)
{
switch (statusLevel) {
case 1:
cout << "[.] " << message;
break;
case 2:
cout << "[+] " << message;
break;
case 3:
cout << "[!] " << message;
break;
case 4:
cout << "[X] " << message;
break;
}
}
Errors:
I get 3 errors.
Visual Studio Error (When you hover it):
Arguments *const this
Pointers to incomplete class is not allowed.
From the error box (Visual Studio):
Error C2027 use of undefined type 'Main' Chek2 c:\users\xxx\documents\programming\c++\vs workspace\chek2\arguments.cpp 30
Error (active) E0393 pointer to incomplete class type is not allowed Chek2 C:\Users\xxx\Documents\Programming\C++\VS Workspace\Chek2\Arguments.cpp 30
Compiler Errors:
1>c:\users\xxx\documents\programming\c++\vs workspace\chek2\arguments.cpp(30): error C2027: use of undefined type 'Main'
1>c:\users\xxx\documents\programming\c++\vs workspace\chek2\arguments.h(3): note: see declaration of 'Main'
If anyone could help me with this. I would highly appreciate it! I hope it's not too hard of a problem- fairly new to C++ so I don't know exactly what this is compared to Java.
Thanks to #drescherjm for answering in comments. I just needed to add:
#include "Main.h"
#include "Core.h"
Inside Arguments.cpp's includes!

How to read data from AVRO file using C++ interface?

I'm attempting to write a simple program to extract some data from a bunch of AVRO files. The schema for each file may be different so I would like to read the files generically (i.e. without having to pregenerate and then compile in the schema for each) using the C++ interface.
I have been attempting to follow the generic.cc example but it assumes a separate schema where I would like to read the schema from each AVRO file.
Here is my code:
#include <fstream>
#include <iostream>
#include "Compiler.hh"
#include "DataFile.hh"
#include "Decoder.hh"
#include "Generic.hh"
#include "Stream.hh"
const std::string BOLD("\033[1m");
const std::string ENDC("\033[0m");
const std::string RED("\033[31m");
const std::string YELLOW("\033[33m");
int main(int argc, char**argv)
{
std::cout << "AVRO Test\n" << std::endl;
if (argc < 2)
{
std::cerr << BOLD << RED << "ERROR: " << ENDC << "please provide an "
<< "input file\n" << std::endl;
return -1;
}
avro::DataFileReaderBase dataFile(argv[1]);
auto dataSchema = dataFile.dataSchema();
// Write out data schema in JSON for grins
std::ofstream output("data_schema.json");
dataSchema.toJson(output);
output.close();
avro::DecoderPtr decoder = avro::binaryDecoder();
auto inStream = avro::fileInputStream(argv[1]);
decoder->init(*inStream);
avro::GenericDatum datum(dataSchema);
avro::decode(*decoder, datum);
std::cout << "Type: " << datum.type() << std::endl;
return 0;
}
Everytime I run the code, no matter what file I use, I get this:
$ ./avrotest twitter.avro
AVRO Test
terminate called after throwing an instance of 'avro::Exception'
what(): Cannot have negative length: -40 Aborted
In addition to my own data files, I have tried using the data files located here: https://github.com/miguno/avro-cli-examples, with the same result.
I tried using the avrocat utility on all of the same files and it works fine. What am I doing wrong?
(NOTE: outputting the data schema for each file in JSON works correctly as expected)
After a bunch more fooling around, I figured it out. You're supposed to use DataFileReader templated with GenericDatum. With the end result being something like this:
#include <fstream>
#include <iostream>
#include "Compiler.hh"
#include "DataFile.hh"
#include "Decoder.hh"
#include "Generic.hh"
#include "Stream.hh"
const std::string BOLD("\033[1m");
const std::string ENDC("\033[0m");
const std::string RED("\033[31m");
const std::string YELLOW("\033[33m");
int main(int argc, char**argv)
{
std::cout << "AVRO Test\n" << std::endl;
if (argc < 2)
{
std::cerr << BOLD << RED << "ERROR: " << ENDC << "please provide an "
<< "input file\n" << std::endl;
return -1;
}
avro::DataFileReader<avro::GenericDatum> reader(argv[1]);
auto dataSchema = reader.dataSchema();
// Write out data schema in JSON for grins
std::ofstream output("data_schema.json");
dataSchema.toJson(output);
output.close();
avro::GenericDatum datum(dataSchema);
while (reader.read(datum))
{
std::cout << "Type: " << datum.type() << std::endl;
if (datum.type() == avro::AVRO_RECORD)
{
const avro::GenericRecord& r = datum.value<avro::GenericRecord>();
std::cout << "Field-count: " << r.fieldCount() << std::endl;
// TODO: pull out each field
}
}
return 0;
}
Perhaps an example like this should be included with libavro...

How to get value from char pointer member of a structure modified in another function

I passed a structure pointer to a function. What I need is to get the string "connection refused"(return from ssh_get_error()) in the main function.
#include <libssh/libssh.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <cstring>
using namespace std;
typedef struct rtns {
bool state;
char* desc;
} rtns;
int connect_host(rtns *con_host) {
const char* desc;
char desc2[1000];
ssh_session my_ssh_session;
int rc;
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK) {
(*con_host).state = false;
desc = ssh_get_error(my_ssh_session);
strcpy(desc2, ssh_get_error(my_ssh_session));
(*con_host).desc = strdup(desc2);
cout << "from connect_host function->" <<con_host->desc << "\n";
} else {
(*con_host).state = true;
}
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
}
int main() {
rtns con_host;
rtns *p = (rtns*) malloc(sizeof(struct rtns));
p = (rtns*) malloc(20);
connect_host(&con_host);
cout << "from main function->" << *(con_host.desc) << "\n\n";
}
Output-
from connect_host function->Connection refused
from main function->C
The problem is that i am only getting one character "C" in the main function. I have some idea that I am doing memory allocation wrong but i have no idea how to do it correctly. I also tried to shift the malloc allocation in con_host function but it didn't work either.
Think about what you are printing. You pass to the stream a char, not a char *:
cout << "from main function->" << *(con_host.desc) << "\n\n";
// *(con_host.desc) = *(char *) = char
// Above is a simplification but you get the point.
So long as con_host.desc is a null terminated c string you can print it like this:
cout << "from main function->" << con_host.desc << "\n\n";
Here is a live example.
It's not memory allocation error. It's caused by the output statement. Change to
cout << "from main function->" << con_host.desc << "\n\n";

Communicating pthread with pipes

im trying to communicate a pthread with a process, using pipes, for a college proyect. i make a struct with the pipes and i pass that structure to the pthread so it can listen on the pipe[0], and on the rest of the code i try to send a string to that running pthread.
Here is my code:
#include <unistd.h>
#include <string>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
#include <pthread.h>
using namespace std;
struct Pipefd{
int pipe[2];
string name;
};
void* listenProcess(void* x){
Pipefd* pf = reinterpret_cast<Pipefd*>(x);
close(0);
dup(pf->pipe[0]);
//here i try to see if the struct i send is ok, but this is not printed.
cout << "pf.name: " << pf->name << endl;
string recive;
while(getline(cin,recive)){
cout << "recive: " << recive << endl;
}
cout << "Problem with getline" << endl;
}
int main(int argc, char *argv[]) {
Pipefd myPipe;
myPipe.name = "Test";
pipe(myPipe.pipe);
void* test = reinterpret_cast<void*>(&myPipe);
pthread_t tid;
pthread_create(&tid,NULL, &listenProcess,test);
close(1);
dup(myPipe.pipe[1]);
cout << "This is a message" << endl;
pthread_join(tid,NULL);
}
if someone can reply me with some ideas of how to make this work it would be awesome, if not, thank you for your time.

How to show terminal in linux application?

I was wondering if you could have it so when you go and click on a program in linux it always automatically brings up the command line for the information being displayed or if I decided to use ncurses for an interface. If so is this a system specific call or can you do this with ncurses? Because half of my program is going to be via terminal.
Thanks
Since nitt wouldn't let me amend his code snippet, I'm posting a corrected snippet in case anyone would like to use it:
#include <cstdio>
#include <unistd.h>
#include <iostream>
int main(int argc, char* argv[])
{
if (isatty(0))
{
std::cout << "Hello, World!" << std::endl;
for (int i=0; i<argc; i++)
std::cout << "arg: " << i << "\t" << argv[i] << std::endl;
std::cout << "Press return to continue . . ." << std::flush;
std::cin.get();
}
else
{
const char* args[argc+3], **it=args;
*it++ = "gnome-terminal";
*it++ = "-x";
it = std::copy(argv, argv+argc, it);
*it++ = 0;
if (-1 == execvp("gnome-terminal", (char* const*) &args[0]))
perror("exec");
}
}
Yes, just invoke a terminal with your app in it. For example:
rxvt -e myapp
Starts a terminal running your app. You could also use xterm. If you want to use wide chars/unicode I recommend rxvt-unicode.
You can put this in a .desktop file with an icon defined there, and then that will be placed in the system menu.
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int fileExists(string x321) {
ifstream x123 (x321.c_str());
string x213;
x123 >> x213;
if (x213 == "") {
return false;
} else {
return true;
}
}
int createConsole(string fname) {
if (fileExists("~tmp") == false) {
ofstream tmp ("~tmp");
tmp << "tmpfile";
fname = "gnome-terminal -e " + fname;
system(fname.c_str());
system("exit");
return 0;
}
remove("~tmp");
return 1;
}
int main(int argc, char** args) {
createConsole(args[0]);
cout << "Hello, World!" << endl;
cout << "Press return to continue . . .";
cin.get();
}
Pay attention to the "createConsole" and "fileExists" function. I wrote this myself.