首页 > 编程语言 >C++ 中环境变量获取,动态库环境变量的传递

C++ 中环境变量获取,动态库环境变量的传递

时间:2024-11-12 11:21:37浏览次数:1  
标签:int pfoo C++ char 获取 printf include 环境变量

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

标签:int,pfoo,C++,char,获取,printf,include,环境变量
From: https://www.cnblogs.com/michaelcjl/p/18541485

相关文章

  • SpringBoot校园电子商务系统884d6 带论文文档1万字以上,文末可获取
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表系统内容:商家,用户,商品分类,商品信息开题报告内容一、课题名称基于SpringBoot的校园电子商务系统研究二、研究背景与意义随着信息技术和互联网的普及,电子商......
  • SpringBoot闲置物品置换平台u3ptr 带论文文档1万字以上,文末可获取
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表系统内容:会员,卖家,物品分类,闲置物品,交易信息,求购信息开题报告内容一、研究背景与意义随着物质生活的丰富和消费观念的转变,人们手中积累的闲置物品日益增......
  • 南沙C++信奥赛老师解一本通题 1385:团伙(group)
    ​【题目描述】在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足:1、我朋友的朋友是我的朋友;2、我敌人的敌人是我的朋友;所有是朋友的人组成一个团伙。告诉你关于这n个人的m条信息,即某两个人是朋友,或者某两个人是敌人,请你编写一个程序,计算出这个城市最多可能有多......
  • C++求最小公倍数与最大公因数
    #大一小卡了咪的作业4题目:        设计两个函数MaxCommonDevisor(n,m) 和MinCommonMultiple(n,m),分别求两个数的最大公约数和最小公倍数。主函数调用上述两个函数,实现功能。    乍一看这个题其实比较麻烦,因为要同时满足两个数的要求(同时整除/分别整除),但实际......
  • C++-模块
    C++20引入了模块(Modules)的概念,这是一项重要的语言特性,旨在改进C++的编译速度和构建过程。模块提供了一种新的组织代码的方式,可以替代传统的头文件包含和预处理器。使用模块可以带来以下几个好处:更快的编译速度:传统的头文件包含方式在编译过程中需要进行大量的文件打开和文本处......
  • 【C++】模板(一):函数模板
    大家好,我是苏貝,本篇博客带大家了解C++的函数模板,如果你觉得我写的还不错的话,可以给我一个赞......
  • 双十一购物攻略:如何利用爬虫技术获取历史价格趋势,理性购物不踩雷
    双十一购物狂欢节即将到来,作为程序员,利用爬虫技术查询商品的历史价格趋势,似乎是一个合理的需求,毕竟这只是为了自己参考,不涉及商业用途。然而,小伙伴们在进行爬虫操作时一定要谨慎小心,尤其是在数据采集和使用的过程中,务必遵守相关法律法规与平台的使用规范。每次和大家讲解爬虫时,我......
  • C++----继承
    目录一.继承的概念及定义1.继承的概念2.继承的定义二.基类和派生类对象赋值转化三.继承中的作用域四.派生类的默认成员函数五.继承和友元六.继承和静态成员七.复杂的菱形继承及菱形虚拟继承八.继承的总结和反思一.继承的概念及定义1.继承的概念继承(inheritanc......
  • C++入门基础(四)
    目录引用的应用做参数做返回值野引用扩展传值、传引用效率比较引用和指针的区别C++对比C语言实现顺序表引用的应用做参数 #include<iostream> usingnamespacestd; voidSwap(int&a,int&b) { inttemp=a; a=b; b=temp; } intmain() { in......
  • C++结构体中的资源释放
    一般情况下,结构体不需要手动释放。如果结构体只包含基本类型(如int、float等)或没有指针成员,其内存由栈或堆自动管理,不需要手动释放。然而,如果结构体包含动态分配的资源(例如指针、文件句柄等),则需要在结构体的生命周期结束时手动释放这些资源。通常可以通过以下方式来管理:使用......