C++ Dynamic Variable - c++

Sorry for not knowing much about C++. There is a problem I can't solve. I want the CONFIG_PATH variable to be dynamic, not fixed. I want it to be replaceable from the outside, but I've never been able to.
string custom_path;
custom_path= argv[i];
I want to replace CONFIG_PATH with custom_path. Or I want to set it as CONFIG_PATH + custom_path
#define CONFIG_PATH "D:/config"
int GetConfigPath(char *path, size_t size, const char *name)
{
if (!OBS_UNIX_STRUCTURE && portable_mode) {
if (name && *name) {
return snprintf(path, size, CONFIG_PATH "/%s", name);
} else {
return snprintf(path, size, CONFIG_PATH);
}
} else {
return snprintf(path, size, CONFIG_PATH "/%s", name);
}
}

I want the CONFIG_PATH variable to be dynamic
CONFIG_PATH isn't a variable in the example. It is a pre-processor macro. It isn't possible to change pre-processor macros at runtime.
You can replace the macro with a variable whose value can be changed at runtime. Example:
std::string CONFIG_PATH;
int main(int argc, char** argv)
{
CONFIG_PATH = argv[i];
As a side-note: Global variables are potentially problematic. Consider alternative designs like for example passing the value as a parameter into the function.

If you remove the #define and instead use std::getenv("CONFIG_PATH") you can export (or whatever it's called in your shell) an environment variable named CONFIG_PATH that you can then read in your program. You must export it before running the program and any changes you make to it outside of your program will not be visible.
You can not concatenate it with other strings like you currently do with the macro though.
const char* config_path = std::getenv("CONFIG_PATH");
if(config_path) {
std::string path_to_foo = std::string(config_path) + "/foo";
// use path_to_foo ...
}

Related

String type alternative in C

I currently have a function defined in a header that looks like this
void foo::GetValue(std::string& str);
This function basically assigns a value to str. I need to come up with an alternative to str (basically, nothing that employs the standard library).
The implementation of the above function is like this in the .cpp file:
void foo::GetValue(std::string& str)
{
std::string s = bar.someMethod();
str = s;
}
I want to know what is the best/easiest option for replacing the header?
One approach I had was to replace std::string in the header file with char* so I would have this in the header:
void foo::GetValue(char* str);
And in the implementation I would have this:
void foo::GetValue(char* str)
{
std::string resp = bar.someMethod();
char* c = new char[resp.size() + 1];
std::copy(resp.begin(), resp.end(), c);
c[resp.size()] = '\0';
}
The problem with the above approach is that a lot of files are calling this function and they will need to modify their code. Also, they will need to free the above memory. Two concerns I have with this is that other callers to this function will need to do the following two things
Replace std::string being passed to the function with char*.
Free the char* when done using it.
These two items seem very costly to me to trust other callers to do.
Any suggestions on what I can do to solve this problem? Perhaps change the signature to something else? I would prefer if the caller still passes a string, however string.c_str() is a constant char pointer.
For a given C++ function like this:
std::string foo::GetValue(std::string& str)
{
return bar.someMethod(str);
}
Then your equivalent C code looks like this:
void foo_GetValue(char* str, char* res, size_t size)
{
std::string str_arg = str;
std::string result = bar.someMethod(str_arg);
strncpy(res, result.c_str(), size - 1);
res[size-1] = 0; // Ensure is NUL terminated
}
When calling from C:
void example() {
const BUFFER_LEN = 1024;
char buffer[BUFFER_LEN];
foo_GetValue("example", buffer, BUFFER_LEN);
}

How to cast const char* to static const char XY[]?

I'm doing some C# code which is using DLLImport to call a function inside my C++ DLL:
[DllImport("my.dll", EntryPoint = "#16", CallingConvention = CallingConvention.StdCall)]
private static extern void sendstring(string s);
I call it like this in C#:
sendstring("Test1\\0test2\\0");
My C++ DLL needs to create a static const char XY[] = "Test1\0test2\0"; from this, since I need that for calling another DLLs function from inside my c++ DLL like this:
functiontootherdll(sizeof(s),(void*)s);
So my code in C++:
extern "C" {
void MyClass::sendstring( const char *s) {
functiontootherdll(sizeof(s),(void*)s);
}
The problem: It is working, if I define the thing manually inside my C++ DLL like this:
static const char Teststring[] = "Test1\0test2\0";
functiontootherdll(sizeof(Teststring),(void*)Teststring);
but it is not taking the const char *s when calling this from my C# file (it will report different errors from the called other dll).
I would need to know how I can cast the const char *s to something like static const char s[] or such.
As you realize I have little clue about all this, so any help is very welcome!
Alright, I found out a way I think:
I modified my C++ to:
extern "C" {
void MyClass::sendstring( const char *s) {
int le = strlen(s);
char p[256];
strcpy(p,s);
char XY[sizeof(p) / sizeof(*p) + 1];
int o=0;
for (int i = 0; i<le;i++) {
if (p[i] == ';') {
XY[i] = '\0';
} else {
XY[i] = p[i];
}
o++;
}
XY[o] = '\0';
functiontootherdll(sizeof(XY),(void*)XY);
}
Afterwards the function call to
functiontootherdll(sizeof(XY),(void*)XY);
is working fine.
Pls note that I send from my C# code now a string like "Test1;test2;test3;...", trying with the \\0 as separator did not work out. My call with C# is:
sendstring("Test1;test2;test3");
I don't know if this is a smart solution, but at least it is one :)

C++ Visual Studio 2010 how to use a char type variable in different functions

I'm having a problem regarding a char type variable in my program.
I don't post the code because it is too long but this is roughly what I want to do:
#include ...
char path[100];
int main()
{
char path[100] = "C:/......";
[...]
out = function();
}
int function()
{
[...]
imwrite(path,image);
[...]
}
The problem is that my path variable seems to be lost somehow because if I try cout < < path before imwrite in function it doesen't print anything as if path was empty.
What should I do forbeing able to access my path variable in function?
You are defining the path variable within the scope of your main function, as well as in the global scope.
In main() you have a new declaration of path:
char path[100] = "...";
This effectively gives you two variables with the same name, but in different scopes. If you access path from within the main method, it will access the locally-scoped variable.
If you wish to keep it this way, and remove the globally-scoped path variable, you could redeclare your function to:
int function(char* p_path)
{
imwrite(p_path, image);
}
and pass the value as a parameter from main:
char path[100] = "...";
...
function(path);
As an aside, you could force access of the globally-scoped variable from within the main method by referencing ::path, which specifies the global namespace. But that's another story.
You're defining a global variable path (in global scope) and a local variable path in main(). This means that inside main(), path refers to the local one, while in function(), it refers to the global one.
If the path is hardcoded (as in the example you gave), you can do this:
#include ...
char path[100] = "C:/......";
int main()
{
[...]
out = function();
}
If the path needs to be computed, do this instead:
#include ...
char path[100];
int main()
{
[...]
std::copy(computedPathValue, computedPathValue + computedPathLength + 1, path);
out = function();
}
Of course, the best would be to have std::string path instead of a char[100].

How to read Linux environment variables in c++

In my c++ program I want to load some environment variables from the shell into some strings. How can this be done?
Use the getenv() function - see http://en.cppreference.com/w/cpp/utility/program/getenv. I like to wrap this as follows:
std::string GetEnv( const std::string & var ) {
const char * val = std::getenv( var.c_str() );
if ( val == nullptr ) { // invalid to assign nullptr to std::string
return "";
}
else {
return val;
}
}
which avoids problems when the environment variable does not exist, and allows me to use C++ strings easily to query the environment. Of course, it does not allow me to test if an environment variable does not exist, but in general that is not a problem in my code.
Same as in C: use getenv(variablename).
You could simply use char* env[]
int main(int argc, char* argv[], char* env[]){
int i;
for(i=0;env[i]!=NULL;i++)
printf("%s\n",env[i]);
return 0;
}
here is a complete article about your problem, from my website.

C++: Define simple constant for use?

In C++ I wanted to define a constant that I can use in another function, A short answer on how to do this will be fine..
Lets say at the beginning of my code I want to define this constant:
//After #includes
bool OS = 1; //1 = linux
if (OS) {
const ??? = "clear";
} else {
const ??? = "cls";
}
I don't know what type to use to define the "clear" string... I'm so confused.
Later on I want to use it within a function:
int foo() {
system(::cls); //:: for global
return 0;
}
How would I define the string up top, and use the string down below? I heard char only had one character and things... I'm not sure how to use , since it says it's converting string into const char or something.
char* isn't quite a char. char* is basically a string (it's what strings were before C++ came along).
For illustration:
int array[N]; // An array of N ints.
char str[N]; // An array of N chars, which is also (loosely) called a string.
char[] degrades to char*, so you'll often see functions take a char*.
To convert std::string to const char*, you can simply call:
std::string s;
s.c_str()
In this case, it's common to use the preprocessor to define your OS. This way you can use the compiler to do the platform specific stuff:
#ifdef OS_LINUX
const char cls[] = "clear";
#elif OS_WIN
const char cls[] = "cls";
#endif
One thing you may want to consider is making it a function. This avoids nasty dependencies of global construction order.
string GetClearCommand() {
if (OS == "LINUX") {
return "clear";
} else if (OS == "WIN") {
return "cls";
}
FAIL("No OS specified?");
return "";
}
What it looks like you're trying to do is this:
#include <iostream>
using namespace std;
#ifdef LINUX
const char cls[] = "LINUX_CLEAR";
#elif WIN
const char cls[] = "WIN_CLEAR";
#else
const char cls[] = "OTHER_CLEAR";
#endif
void fake_system(const char* arg) {
std::cout << "fake_system: " << arg << std::endl;
}
int main(int argc, char** argv) {
fake_system(cls);
return 0;
}
// Then build the program passing your OS parameter.
$ g++ -DLINUX clear.cc -o clear
$ ./clear
fake_system: LINUX_CLEAR
Here's the problem, you're suffering from going out of scope with the variables. If I declare something within brackets, it only exists within the brackets.
if( foo ){
const char* blah = "blah";
}
Once we leave the if statement, the variable blah disappears. You'll need to instantiate it non-locally to whatever brackets you write. Hence:
void Bar(){
const char* blah = "blah";
if( foo ){
//blah exists within here
}
}
However, blah will not exist outside of Bar. Get it?
Yet another option is to create a class with a bunch of static methods. Create a new method for each command. Something like:
// in sys-commands.h
class SystemCommands {
public:
static char const* clear();
static char const* remove();
};
This gives you a few nice options for the implementation. The nicest one is to have a separate implementation file for each platform that you select during compile time.
// in sys-commands-win32.cpp
#include "sys-commands.h"
char const* SystemCommands::clear() { return "cls"; }
char const* SystemCommands::remove() { return "erase /f/q"; }
// in sys-commands-macosx.cpp
#include "sys-commands.h"
char const* SystemCommands::clear() { return "/usr/bin/clear"; }
char const* SystemCommands::remove() { return "/bin/rm -fr"; }
Which file gets compiled will determine which command set will be used. Your application code will look like:
#include <cstdlib>
#include "sys-commands.h"
int main() {
std::system(SystemCommands::clear());
return 0;
}
Edit: I forgot to mention that I prefer static functions to global constants for a bunch of reasons. If nothing else, you can make them non-constant without changing their types - in other words, if you ever have to select the command set based on runtime settings, the user code does not have to change or even be aware that such a change occurred.
You can use a common header file and link to different modules depending on the systen:
// systemconstants.hpp
#ifndef SYSTEM_CONSTANTS_HPP_INCLUDED
#define SYSTEM_CONSTANTS_HPP_INCLUDED
namespace constants {
extern const char cls[]; // declaration of cls with incomplete type
}
#endif
In case of Linux, just compile and link to this one:
// linux/systemconstants.cpp
#include "systemconstants.hpp"
namespace constants {
extern const char cls[] = "clear";
}
In case of Windows, just compile and link to this one:
// windows/systemconstants.cpp
#include "systemconstants.hpp"
namespace constants {
extern const char cls[] = "cls";
}
System-specific translation units could be placed in specific subdirectories (linux/, windows/, etc) of which one could be automatically selected during the build process. This extends to many other things, not just string constants.