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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!