C++ 中环境变量获取,动态库环境变量的传递
C++ 中环境变量获取,动态库环境变量的传递
在实践中,考虑最好还是使用getenv()函数来取得相关的环境变量.
C/C++ 获取系统环境变量,其实是很简单的.
函数名: getenv
功 能: 从环境中取字符串,获取环境变量的值
头文件: stdlib.h
用 法: char *getenv(char *envvar);
getenv()用来取得参数envvar环境变量的内容。参数envvar为环境变量的名称,如果该变量存在则会返回指向该内容的指针。环境变量的格式为envvar=value。getenv函数的返回值存储在一个全局二维数组里,当你再次使用getenv函数时不用担心会覆盖上次的调用结果。
返回值: 执行成功则返回指向该内容的指针,找不到符合的环境变量名称则返回NULL。如果变量存在但无关联值,它将运行成功并返回一个空字符串,即该字符的第一个字节是null。
下面是一个单纯c语言获取的方式.
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *pathvar;
pathvar = getenv("PATH");
printf("pathvar=%s",pathvar);
return 0;
}
注: 需要注意的是,getenv()
函数定义在 stdlib.h
中,如果在C++中使用,可以通过 #include <cstdlib>
并使用 std::getenv()
函数。为了考虑可移植性,这两种方法都是首选。
在windows环境下,我们也可以用WINAPI GetEnvironmentVariable() 来获取某个环境变量的值.
我们还有两种方式,可以列出当前设定的所有的环境变量的值.
- envp
// Original Code
#include <stdio.h>
int main(int argc, char **argv, char **envp) {
char **env;
for (env = envp; *env != 0; env++) {
char *thisEnv = *env;
printf("%s\n", thisEnv);
}
}
// Modified Code
#include <stdio.h>
int main(int argc, char **argv, char **envp) {
char **environment;
for (environment = envp; *environment != 0; environment++) {
char *currentEnv = *environment;
printf("%s\n", currentEnv);
}
}
备注:这里需要强调的是,关于envp,若要考虑程序的可携带性,最好不使用envp作为main函数的第三个参数。
这是一种常见于Unix系列系统的扩展功能。envp是一个以null结尾的字符串数组,在Microsoft C++中也能使用。如果你使用的是wmain,可以用wchar_t代替char来表示。
尽管这是一个常见的扩展功能,但并非所有系统都支持此扩展。因此,在考虑程序的可携带性时,最好不要使用它。
根据C99标准,只有两种合法的main函数定义:
a) int main(void)
b) int main(int argc, char **argv)或等效形式 它允许实现定义其他格式(其中可能会允许第三个参数)
c) 或以其他一些实现定义的方式。
C++动态库环境变量的传递
某工程使用到一动态库,内部通过环境变量来控制是否打印某些执行过程的日志。
在应用程序使用setenv
设置环境变量,动态库内使用getenv
获取环境变量,再修改,最后应用程序读取。
动态库的加载使用dlopen
函数,调用函数使用dlsym
,这样能分离动态库,编译应用程序时不需要依赖so文件 。
dl.h头文件:
#ifndef DL_H
#define DL_H
#ifdef __cplusplus
extern "C" {
#endif
// 使用结构体管理库函数
typedef struct {
const char *name; // 名称
// 函数
int (*GetVersion)(char *version);
int (*Foo)();
int (*Bar)();
} DL_API_t;
// 单独的函数
int foo();
int bar();
int env_test();
extern DL_API_t gAPI;
#ifdef __cplusplus
}
#endif
#endif
dl.cpp实现代码:
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "dl.h"
int GetVersion(char *version)
{
int ver = 10;
sprintf(version, "ver: 0.%d", ver);
return 0;
}
int Foo()
{
printf("Foo...\n");
return 0;
}
int Bar()
{
printf("Bar...\n");
return 0;
}
DL_API_t gAPI = {
.name = "MyLib",
GetVersion,
Foo,
Bar,
};
///////////////
int foo()
{
printf("foo...\n");
return 0;
}
int bar()
{
printf("bar...\n");
return 0;
}
int env_test()
{
printf("get env in so lib...\n");
char* value = getenv("FOOBAR");
printf("FOOBAR: %s\n", value); // 不存在的环境变量
value = getenv("FOO");
printf("FOO: %s\n", value);
value = getenv("BAR");
printf("BAR: %s\n", value);
setenv("BAR", "bar 250", 1);
return 0;
}
测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
#include <string.h>
#include <errno.h>
#include "dl.h"
typedef int (*pfoo_t)();
pfoo_t pfoo;
int mysetenv(const char* env, const char* value)
{
if(setenv(env, value, 1) != 0)
{
printf("setenv %s failed %d: %s\n", env, errno, strerror(errno));
}
return 0;
}
int main(void)
{
void* handle = NULL;
char version[64] = {0};
printf("so test...\n");
DL_API_t* aLib = NULL;
// 在加载动态库前设置
//mysetenv("FOO", "foo");
//mysetenv("BAR", "bar");
handle = dlopen("./libfoobar.so", RTLD_LAZY); // 必须加路径
if (handle == NULL)
{
printf("open failed.\n");
return -1;
}
aLib = (DL_API_t*)dlsym(handle, "gAPI");
if (!aLib)
{
printf("dlsym failed: %s\n", dlerror());
return -1;
}
aLib->GetVersion(version);
printf("ver: %s\n", version);
/*
if (aLib->Foo)
{
aLib->Foo();
}
// 另一方式
pfoo = (pfoo_t)dlsym(handle, "foo");
if (pfoo)
{
pfoo();
}
// 注:foo和bar的形式一样,可复用指针
pfoo = (pfoo_t)dlsym(handle, "bar");
if (pfoo)
{
pfoo();
}
*/
mysetenv("FOO", "foo");
mysetenv("BAR", "bar");
// 注:复用指针
pfoo = (pfoo_t)dlsym(handle, "env_test");
if (pfoo)
{
pfoo();
}
char* value = getenv("BAR");
printf("BAR in main: %s\n", value);
dlclose(handle);
return 0;
}
测试结果:
$ ./a.out
so test...
ver: ver: 0.10
get env in so lib...
FOOBAR: (null)
FOO: foo
BAR: bar
BAR in main: bar 250
https://www.cnblogs.com/2467118965z/p/17620176.html
https://juejin.cn/post/7103428427637604382