我正在尝试在 Windows 上使用混淆库。在 vc++ 中编译混淆时出现链接时间错误。如何解决它。请注意,libConfuse 是一个配置文件解析器库,用 C 语言编写。
1>Linking...
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_opt_getnint referenced in function "void __cdecl print_ask(struct cfg_opt_t *,unsigned int,struct _iobuf *)" (?print_ask@@YAXPAUcfg_opt_t@@IPAU_iobuf@@@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_title referenced in function "int __cdecl cb_validate_bookmark(struct cfg_t *,struct cfg_opt_t *)" (?cb_validate_bookmark@@YAHPAUcfg_t@@PAUcfg_opt_t@@@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_getstr referenced in function "int __cdecl cb_validate_bookmark(struct cfg_t *,struct cfg_opt_t *)" (?cb_validate_bookmark@@YAHPAUcfg_t@@PAUcfg_opt_t@@@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_opt_getnsec referenced in function "int __cdecl cb_validate_bookmark(struct cfg_t *,struct cfg_opt_t *)" (?cb_validate_bookmark@@YAHPAUcfg_t@@PAUcfg_opt_t@@@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_opt_size referenced in function "int __cdecl cb_validate_bookmark(struct cfg_t *,struct cfg_opt_t *)" (?cb_validate_bookmark@@YAHPAUcfg_t@@PAUcfg_opt_t@@@Z)
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_free referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_print referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_set_print_func referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_getnint referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_getnfloat referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_getnstr referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_getsec referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_getbool referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_getnsec referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_size referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_setstr referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_getint referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_parse referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_set_validate_func referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_init referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol __imp__cfg_include referenced in function _main
1>F:\products\testconfuse\testconfuse\Debug\testconfuse.exe : fatal error LNK1120: 21 unresolved externals
1>Build log was saved at "file://f:\products\testconfuse\testconfuse\testconfuse\Debug\BuildLog.htm"
1>testconfuse - 22 error(s), 0 warning(s)
该程序有两个文件 main.cpp 和 test.conf 。也不是我们需要下载http://bzero.se/confuse/confuse-2.6.zip并使用库 libConfuse.lib,它存在于 confuse-2.6\windows\msvc6\libConfuse
///// main.cpp
extern "C"
{
#include <confuse.h>
}
#include <string.h>
void print_func(cfg_opt_t *opt, unsigned int index, FILE *fp)
{
fprintf(fp, "%s(foo)", opt->name);
}
void print_ask(cfg_opt_t *opt, unsigned int index, FILE *fp)
{
int value = cfg_opt_getnint(opt, index);
switch(value) {
case 1:
fprintf(fp, "yes");
break;
case 2:
fprintf(fp, "no");
break;
case 3:
default:
fprintf(fp, "maybe");
break;
}
}
/* function callback
*/
int cb_func(cfg_t *cfg, cfg_opt_t *opt, int argc, const char **argv)
{
int i;
/* at least one parameter is required */
if(argc == 0) {
cfg_error(cfg, "Too few parameters for the '%s' function",
opt->name);
return -1;
}
printf("cb_func() called with %d parameters:\n", argc);
for(i = 0; i < argc; i++)
printf("parameter %d: '%s'\n", i, argv[i]);
return 0;
}
/* value parsing callback
*
* VALUE must be "yes", "no" or "maybe", and the corresponding results
* are the integers 1, 2 and 3.
*/
int cb_verify_ask(cfg_t *cfg, cfg_opt_t *opt, const char *value, void *result)
{
if(strcmp(value, "yes") == 0)
*(long int *)result = 1;
else if(strcmp(value, "no") == 0)
*(long int *)result = 2;
else if(strcmp(value, "maybe") == 0)
*(long int *)result = 3;
else {
cfg_error(cfg, "Invalid value for option %s: %s", opt->name, value);
return -1;
}
return 0;
}
int cb_validate_bookmark(cfg_t *cfg, cfg_opt_t *opt)
{
/* only validate the last bookmark */
cfg_t *sec = cfg_opt_getnsec(opt, cfg_opt_size(opt) - 1);
if(!sec)
{
cfg_error(cfg, "section is NULL!?");
return -1;
}
if(cfg_getstr(sec, "machine") == 0)
{
cfg_error(cfg, "machine option must be set for bookmark '%s'",
cfg_title(sec));
return -1;
}
return 0;
}
int main(int argc, char **argv)
{
unsigned int i;
cfg_t *cfg;
unsigned n;
int ret;
static cfg_opt_t proxy_opts[] = {
CFG_INT("type", 0, CFGF_NONE),
CFG_STR("host", 0, CFGF_NONE),
CFG_STR_LIST("exclude", "{localhost, .localnet}", CFGF_NONE),
CFG_INT("port", 21, CFGF_NONE),
CFG_END()
};
static cfg_opt_t bookmark_opts[] = {
CFG_STR("machine", 0, CFGF_NONE),
CFG_INT("port", 21, CFGF_NONE),
CFG_STR("login", 0, CFGF_NONE),
CFG_STR("password", 0, CFGF_NONE),
CFG_STR("directory", 0, CFGF_NONE),
CFG_BOOL("passive-mode", cfg_false, CFGF_NONE),
CFG_SEC("proxy", proxy_opts, CFGF_NONE),
CFG_END()
};
cfg_opt_t opts[] = {
CFG_INT("backlog", 42, CFGF_NONE),
CFG_STR("probe-device", "eth2", CFGF_NONE),
CFG_SEC("bookmark", bookmark_opts, CFGF_MULTI | CFGF_TITLE),
CFG_FLOAT_LIST("delays", "{3.567e2, 0.2, -47.11}", CFGF_NONE),
CFG_FUNC("func", &cb_func),
CFG_INT_CB("ask-quit", 3, CFGF_NONE, &cb_verify_ask),
CFG_INT_LIST_CB("ask-quit-array", "{maybe, yes, no}",
CFGF_NONE, &cb_verify_ask),
CFG_FUNC("include", &cfg_include),
CFG_END()
};
#ifndef _WIN32
/* for some reason, MS Visual C++ chokes on this (?) */
printf("Using %s\n\n", confuse_copyright);
#endif
cfg = cfg_init(opts, CFGF_NOCASE);
/* set a validating callback function for bookmark sections */
cfg_set_validate_func(cfg, "bookmark", &cb_validate_bookmark);
ret = cfg_parse(cfg, argc > 1 ? argv[1] : "test.conf");
printf("ret == %d\n", ret);
if(ret == CFG_FILE_ERROR) {
perror("test.conf");
return 1;
} else if(ret == CFG_PARSE_ERROR) {
fprintf(stderr, "parse error\n");
return 2;
}
printf("backlog == %ld\n", cfg_getint(cfg, "backlog"));
printf("probe device is %s\n", cfg_getstr(cfg, "probe-device"));
cfg_setstr(cfg, "probe-device", "lo");
printf("probe device is %s\n", cfg_getstr(cfg, "probe-device"));
n = cfg_size(cfg, "bookmark");
printf("%d configured bookmarks:\n", n);
for(i = 0; i < n; i++) {
cfg_t *pxy;
cfg_t *bm = cfg_getnsec(cfg, "bookmark", i);
printf(" bookmark #%u (%s):\n", i+1, cfg_title(bm));
printf(" machine = %s\n", cfg_getstr(bm, "machine"));
printf(" port = %d\n", (int)cfg_getint(bm, "port"));
printf(" login = %s\n", cfg_getstr(bm, "login"));
printf(" passive-mode = %s\n",
cfg_getbool(bm, "passive-mode") ? "true" : "false");
printf(" directory = %s\n", cfg_getstr(bm, "directory"));
printf(" password = %s\n", cfg_getstr(bm, "password"));
pxy = cfg_getsec(bm, "proxy");
if(pxy) {
int j, m;
if(cfg_getstr(pxy, "host") == 0) {
printf(" no proxy host is set, setting it to 'localhost'...\n");
/* For sections without CFGF_MULTI flag set, there is
* also an extended syntax to get an option in a
* subsection:
*/
cfg_setstr(bm, "proxy|host", "localhost");
}
printf(" proxy host is %s\n", cfg_getstr(pxy, "host"));
printf(" proxy type is %ld\n", cfg_getint(pxy, "type"));
printf(" proxy port is %ld\n", cfg_getint(pxy, "port"));
m = cfg_size(pxy, "exclude");
printf(" got %d hosts to exclude from proxying:\n", m);
for(j = 0; j < m; j++) {
printf(" exclude %s\n", cfg_getnstr(pxy, "exclude", j));
}
} else
printf(" no proxy settings configured\n");
}
printf("delays are (%d):\n", cfg_size(cfg, "delays"));
for(i = 0; i < cfg_size(cfg, "delays"); i++)
printf(" %G\n", cfg_getnfloat(cfg, "delays", i));
printf("ask-quit == %ld\n", cfg_getint(cfg, "ask-quit"));
/* Using cfg_setint(), the integer value for the option ask-quit
* is not verified by the value parsing callback.
*
*
cfg_setint(cfg, "ask-quit", 4);
printf("ask-quit == %ld\n", cfg_getint(cfg, "ask-quit"));
*/
/* The following commented line will generate a failed assertion
* and abort, since the option "foo" is not declared
*
*
printf("foo == %ld\n", cfg_getint(cfg, "foo"));
*/
cfg_addlist(cfg, "ask-quit-array", 2, 1, 2);
for(i = 0; i < cfg_size(cfg, "ask-quit-array"); i++)
printf("ask-quit-array[%d] == %ld\n",
i, cfg_getnint(cfg, "ask-quit-array", i));
/* print the parsed values to another file */
{
FILE *fp = fopen("test.conf.out", "w");
cfg_set_print_func(cfg, "func", print_func);
cfg_set_print_func(cfg, "ask-quit", print_ask);
cfg_set_print_func(cfg, "ask-quit-array", print_ask);
cfg_print(cfg, fp);
fclose(fp);
}
cfg_free(cfg);
return 0;
}
// test.conf
# test config file
# this is a one line comment
// this is a C++-style one line comment
/*
* This is a C-style multi-line comment
*/
BackLog = 2147483647
bookmark heimdal {
login = "anonymous"
password = ${ANONPASS:-anonymous@}
directory = "/pub/heimdal/src"
machine = "ftp://ftp.pdc.kth.se:21"
proxy {
type = 1
host = ${HOST:-localhost} # environment variable substitution
#port = 21
#exclude = {"localhost" , ".localnet" , "fu.bar.net"}
exclude += {.aol.com , .sf.net}
}
}
probe-device = "eth1"
# probe-device += "eth3" # error, probe-device is not a list
bookmark gazonk {
machine = "ssh://localhost"
login = joe
passive-mode = true
directory = '/pub/dir with spaces/\
more' # continued on next line
port = 022 # in octal mode
proxy {} /* use default proxy */
}
bookmark ftp.du.se {
machine = "ftp.du.se"
// port = 0x21 /* hexadecimal */
login = ftp
proxy {
exclude = {.com.net}
}
}
/* functions can be called with variable number of arguments
*/
func( "one", "two", 'three',four )
func( 1, 2 )
//delays = {145.12345, .6,42, 4.987e2}
//delays += {0.1, 0.2, 0.3}
ask-quit = maybe
#ask-quit-array = {"maybe", "maybe", "maybe"}
ask-quit-array += {"no", "yes", "yes"}
include(inc.conf)
/////////////////////////////////
我在 linker->input->"additional depenendencies" 中添加了 libconfuse.lib,并且还给出了 lib linker->General ->"additional link directory" 的路径
我添加了 libconfuse 2.6 并提取了它。我在它的 src 目录中也使用了 lib config.h。然后我从 libconfuse 主页编译了示例程序。