1. 获取当前处理文件的文件名及行号,属于系统级全局变量:
__FILE__ && __LINE__
2. 宏的定义中 ##表示字符的连接符:
void Create##FuncName(){};
3. C++ 动态库编译示例
g++ DllCall.cpp -fpic -shared -g -o libDllCall.so
g++ Run.cpp -g -ldl -o Run
//DllCall.h头文件
#ifndef _DLL_CALL_
#define _DLL_CALL_
#ifdef WIN32
#ifdef DLLCALL_EXPORT
#define DLLCALL_API extern "C" _declspec(export)
#else
#define DLLCALL_API extern "C" _declspec(import)
#endif
#else
#define DLLCALL_API extern "C"
#endif
DLLCALL_API void test();
#endif
//DllCall.cpp
#include "DllCall.h"
#include <iostream>
DLLCALL_API void test() {
std::cout << "Just test dynamic library ..." << std::endl;
}
/* 对于dlopen函数的打开模式,参见如下官方解释
* One of the following two values must be included in flag:
*
* RTLD_LAZY
* Perform lazy binding. Only resolve symbols as the code that references them is executed. If the symbol is never
* referenced, then it is never resolved. (Lazy binding is only performed for function references; references to
* variables are always immediately bound when the library is loaded.)*
* RTLD_NOW
* If this value is specified, or the environment variable LD_BIND_NOW is set to a non-empty string, all undefined
* symbols in the library are resolved before dlopen() returns. If this cannot be done, an error is returned.
*
* Zero of more of the following values may also be ORed in flag:
*
* RTLD_GLOBAL
* The symbols defined by this library will be made available for symbol resolution of subsequently loaded libraries.*
* RTLD_LOCAL
* This is the converse of RTLD_GLOBAL, and the default if neither flag is specified. Symbols defined in this
* library are not made available to resolve references in subsequently loaded libraries.
* RTLD_NODELETE (since glibc 2.2)
* Do not unload the library during dlclose(). Consequently, the library's static variables are not reinitialised if
* the library is reloaded with dlopen() at a later time. This flag is not specified in POSIX.1-2001.
* RTLD_NOLOAD (since glibc 2.2)
* Don't load the library. This can be used to test if the library is already resident (dlopen() returns NULL if it
* is not, or the library's handle if it is resident). This flag can also be used to promote the flags on a library
* that is already loaded. For example, a library that was previously loaded with RTLD_LOCAL can be re-opened with
* RTLD_NOLOAD | RTLD_GLOBAL. This flag is not specified in POSIX.1-2001.
* RTLD_DEEPBIND (since glibc 2.3.4)
* Place the lookup scope of the symbols in this library ahead of the global scope. This means that a self-contained
* library will use its own symbols in preference to global symbols with the same name contained in libraries that
* have already been loaded. This flag is not specified in POSIX.1-2001.
*/
//部分调用动态库函数代码
typedef void* (*FuncName)();
void* handle = dlopen("libDllCall.so", RTLD_LAZY);
if(handle == NULL) {
std::cout << "Open Dynamic Library failed: " << dlerror() << std::endl;
exit(1);
}
FuncName funcName = (FuncName)dlsym(handle, "test");
if(funcName == NULL) {
std::cout << "Retrive func failed: " << dlerror() << std::endl;
dlclose(handle);
exit(1);
}
funcName();
dlclose(handle);
4. 处理程序的命令行参数
/*
* 关于getopt_long的用法, 如下参见其官方解释, 来至于man getopt_long
* The getopt_long() function works like getopt() except that it also accepts long options, started out by two dashes. (If
* the program accepts only long options, then optstring should be specified as an empty string (""), not NULL.) Long
* option names may be abbreviated if the abbreviation is unique or is an exact match for some defined option. A long
* option may take a parameter, of the form --arg=param or --arg param.
*
* longopts is a pointer to the first element of an array of struct option declared in <getopt.h> as
*
* struct option {
* const char *name;
* int has_arg;
* int *flag;
* int val;
* };
*
* The meanings of the different fields are:
*
* name is the name of the long option.
*
* has_arg
* is: no_argument (or 0) if the option does not take an argument; required_argument (or 1) if the option requires an
* argument; or optional_argument (or 2) if the option takes an optional argument.
*
* flag specifies how results are returned for a long option. If flag is NULL, then getopt_long() returns val. (For
* example, the calling program may set val to the equivalent short option character.) Otherwise, getopt_long()
* returns 0, and flag points to a variable which is set to val if the option is found, but left unchanged if the
* option is not found.
*
* val is the value to return, or to load into the variable pointed to by flag.
*
* The last element of the array has to be filled with zeroes.
*
* If longindex is not NULL, it points to a variable which is set to the index of the long option relative to longopts.
*/
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include <getopt.h>
#define cout std::cout
#define endl std::endl
const char* program_name;
void print_usage(FILE* stream, int exitcode) {
fprintf(stream, "Usage: %s options [ inputfile ...]\n", program_name);
fprintf(stream,
" -h --help Dispaly this usage information.\n"
" -o --output filename Write output to file.\n"
" -v --verbose Dispaly verbose information.\n");
std::exit(exitcode);
}
int main(int argc, char **argv) {
cout << "Hello World!!!" << endl;
int next_option;
const char* const short_options = "ho:v";
const struct option long_options[] = {
{"help", 0, NULL, 'h'},
{"output", 0, NULL, 'o'},
{"verbose", 0, NULL, 'v'},
{NULL, 0, NULL, 0},
};
const char* output_filename = NULL;
int verbose = 0;
program_name = argv[0];
do {
next_option = getopt_long(argc, argv, short_options, long_options, NULL);
switch (next_option) {
case 'h':
print_usage(stdout, 0);
case 'o':
output_filename = optarg;
break;
case 'v':
verbose = 1;
break;
case '?':
print_usage(stderr, 1);
case -1:
break;
default:
std::abort();
}
} while(next_option != -1);
if(verbose) {
int var;
for (var = optind; var < argc; ++var) {
printf("Argument: %s\n", argv[var]);
}
}
return 0;
}