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() 来获取某个环境变量的值.

我们还有两种方式,可以列出当前设定的所有的环境变量的值.

  1. 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

posted @ 2024-11-12 11:24  michaelchengjl  阅读(31)  评论(0编辑  收藏  举报