c++ - GNU 链接器 : errors if pointer in header file is declared NULL and/or extern

标签 c++ c gcc makefile

<分区>

我正在为 BOINC 客户端(C++ 语言)测试一些补丁(C 语言),在编译过程中我得到了关于 GDBusProxy* proxy = NULL; 文件 linux 行的 GNU 链接器错误/user_idle_time_detection.h(下面的完整文件)。所以我开始尝试修改受影响的行,但我遇到了两个不同的错误(下面的情况 1 和 2),我真的不明白为什么链接器不喜欢:

  • 外部声明
  • 初始化为NULL的指针;

谢谢

案例 1

extern GDBusProxy* proxy;

返回错误

/usr/bin/ld: boinc_client-user_idle_time_detection.o: in function `create_proxy':
/builddir/build/BUILD/boinc-client_release-7.14-7.14.2/client/linux/user_idle_time_detection.c:5: undefined reference to `proxy'
/usr/bin/ld: boinc_client-user_idle_time_detection.o: in function `get_user_idle_time':
/builddir/build/BUILD/boinc-client_release-7.14-7.14.2/client/linux/user_idle_time_detection.c:21: undefined reference to `proxy'
collect2: error: ld returned 1 exit status

案例 2

两者

extern GDBusProxy* proxy = NULL;

GDBusProxy* proxy = NULL;

返回错误

/usr/bin/ld: boinc_client-hostinfo_unix.o:/builddir/build/BUILD/boinc-client_release-7.14-7.14.2/client/linux/user_idle_time_detection.h:7: multiple definition of `proxy'; boinc_client-user_idle_time_detection.o:/builddir/build/BUILD/boinc-client_release-7.14-7.14.2/client/linux/user_idle_time_detection.h:7: first defined here

案例 3

下面的效果很好

GDBusProxy* proxy;

源文件

linux/user_idle_time_detection.h

#ifndef USER_IDLE_TIME_DETECTION_H
#define USER_IDLE_TIME_DETECTION_H
#include <gio/gio.h>
#include "gnome/gnome_dbus_interface.h"

GDBusProxy* proxy = NULL;
GDBusProxy* create_proxy();
double get_user_idle_time();
#endif /* USER_IDLE_TIME_DETECTION_H */

linux/user_idle_time_detection.c

#include <gio/gio.h>
#include "user_idle_time_detection.h"
GDBusProxy* create_proxy()
{
    proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
                                           G_DBUS_PROXY_FLAGS_NONE,
                                           NULL,
                                           GNOME_DBUS_SERVICE,
                                           GNOME_DBUS_PATH_SETTINGS,
                                           GNOME_DBUS_INTERFACE_SETTINGS,
                                           NULL, NULL);
    return proxy;
}

double get_user_idle_time()
{
    guint64 user_idle_time;
    double user_idle_time_double;
    GError* error = NULL;
    GVariant* ret = NULL;
    proxy = create_proxy();

    ret = g_dbus_proxy_call_sync(proxy,
                                  GNOME_DBUS_METHOD_SETTINGS,
                                  NULL,
                                  G_DBUS_CALL_FLAGS_NONE, -1,
                                  NULL, &error);
    if (!ret) {
        g_dbus_error_strip_remote_error (error);
        g_print ("GetIdletime failed: %s\n", error->message);
        g_error_free (error);
        return;
    }

    g_variant_get(ret, "(t)", &user_idle_time);
    user_idle_time_double = (double)user_idle_time;
    g_variant_unref (ret);
    return user_idle_time_double;
}

linux/gnome/gnome_dbus_interface.h

#ifndef GNOME_DBUS_INTERFACE_H
#define GNOME_DBUS_INTERFACE_H

#define GNOME_DBUS_SERVICE "org.gnome.Mutter.IdleMonitor"
#define GNOME_DBUS_PATH_SETTINGS "/org/gnome/Mutter/IdleMonitor/Core"
#define GNOME_DBUS_INTERFACE_SETTINGS "org.gnome.Mutter.IdleMonitor"
#define GNOME_DBUS_METHOD_SETTINGS "GetIdletime"
#endif /* GNOME_DBUS_INTERFACE_H */

hostinfo_unix.cpp

#include "linux/user_idle_time_detection.h"
CUT
bool HOST_INFO::users_idle(bool check_all_logins, double idle_time_to_run) {
    double user_idle_time;
    double user_pref_idle_time_in_ms;
    //user_idle_time = get_user_idle_time();
    user_pref_idle_time_in_ms = (idle_time_to_run * 60000);
CUT

Makefile.am

## -*- mode: makefile; tab-width: 4 -*-
## $Id$

include $(top_srcdir)/Makefile.incl

if ENABLE_CLIENT_RELEASE
  AM_LDFLAGS += -static-libtool-libs
## for an entirely statically linked library, you may want to try
## -all-static instead.  There's a good chance it won't work properly,
## so we'll use the safer "-static-libtool-libs" by default.
else
if DYNAMIC_CLIENT
## if libtool starts to need flags for dynamic linking, add them here
else
  AM_LDFLAGS += -static
endif
endif ## ENABLE_CLIENT_RELEASE

LIBS += $(CLIENTLIBS)

if OS_DARWIN
   LIBS += -framework IOKit -framework Foundation -framework ScreenSaver -framework Cocoa -framework CoreServices
endif

bin_PROGRAMS = boinc_client boinccmd
if !OS_WIN32
bin_PROGRAMS += switcher
endif

boinccmd_SOURCES = boinc_cmd.cpp
boinccmd_DEPENDENCIES = $(LIBBOINC)
boinccmd_CPPFLAGS = $(AM_CPPFLAGS)
boinccmd_LDFLAGS = $(AM_LDFLAGS) -L$(top_srcdir)/lib
boinccmd_LDADD = $(LIBBOINC) $(BOINC_EXTRA_LIBS) $(PTHREAD_LIBS)

boinc_client_SOURCES = \
    acct_mgr.cpp \
    acct_setup.cpp \
    app.cpp \
    app_config.cpp \
    app_control.cpp \
    app_start.cpp \
    async_file.cpp \
    check_state.cpp \
    client_msgs.cpp \
    client_state.cpp \
    client_types.cpp \
    coproc_sched.cpp \
    cpu_sched.cpp \
    cs_account.cpp \
    cs_apps.cpp \
    cs_benchmark.cpp \
    cs_cmdline.cpp \
    cs_files.cpp \
    cs_notice.cpp \
    cs_platforms.cpp \
    cs_prefs.cpp \
    cs_proxy.cpp \
    cs_scheduler.cpp \
    cs_statefile.cpp \
    cs_trickle.cpp \
    current_version.cpp \
    dhrystone.cpp \
    dhrystone2.cpp \
    file_names.cpp \
    file_xfer.cpp \
    gpu_amd.cpp \
    gpu_detect.cpp \
    gpu_intel.cpp \
    gpu_nvidia.cpp \
    gpu_opencl.cpp \
    gui_http.cpp \
    gui_rpc_server.cpp \
    gui_rpc_server_ops.cpp \
    hostinfo_linux.cpp \
    hostinfo_network.cpp \
    http_curl.cpp \
    log_flags.cpp \
    mac_address.cpp \
    main.cpp \
    net_stats.cpp \
    pers_file_xfer.cpp \
    project.cpp \
    project_list.cpp \
    result.cpp \
    rr_sim.cpp \
    sandbox.cpp \
    scheduler_op.cpp \
    thread.cpp \
    time_stats.cpp \
    whetstone.cpp \
    work_fetch.cpp \
    linux/user_idle_time_detection.c

boinc_client_DEPENDENCIES = $(LIBBOINC)
boinc_client_CPPFLAGS = $(AM_CPPFLAGS) $(GIO_CFLAGS) $(GLIB_CFLAGS)
boinc_client_CXXFLAGS = $(AM_CXXFLAGS) $(SSL_CXXFLAGS)
boinc_client_LDFLAGS = $(AM_LDFLAGS) $(SSL_LDFLAGS) $(GIO_LIBS) $(GLIB_LIBS)  -L$(top_srcdir)/lib
if OS_WIN32
boinc_client_CXXFLAGS += -I$(top_srcdir)/coprocs/NVIDIA/include
boinc_client_SOURCES += hostinfo_win.cpp \
    hostinfo_wsl.cpp \
    sysmon_win.cpp \
    win/boinc_cli.rc \
    win/res/boinc.ico
else
if OS_DARWIN
boinc_client_LDFLAGS += -Wl,-flat_namespace,-undefined,dynamic_lookup
else
boinc_client_SOURCES += hostinfo_unix.cpp
endif
endif
boinc_client_LDADD = $(LIBBOINC) $(LIBBOINC_CRYPT) $(BOINC_EXTRA_LIBS) $(PTHREAD_LIBS)

boinc_clientdir = $(bindir)

if OS_ARM_LINUX
boinc_client_LDADD += libwhetneon.a libwhetvfp.a
noinst_LIBRARIES = libwhetneon.a libwhetvfp.a
libwhetneon_a_SOURCES = whetstone.cpp
libwhetneon_a_CXXFLAGS = $(boinc_client_CXXFLAGS) -DANDROID_NEON -mfloat-abi=softfp -mfpu=neon

libwhetvfp_a_SOURCES = whetstone.cpp
libwhetvfp_a_CXXFLAGS = $(boinc_client_CXXFLAGS) -DANDROID_VFP -mfloat-abi=softfp -mfpu=vfp
endif

switcher_SOURCES = switcher.cpp
switcher_LDFLAGS = $(AM_LDFLAGS) -L../lib
switcher_LDADD = $(LIBBOINC)

## since we are using libtool we need some magic to get boinc and boinc_client
## to both be installed properly.  The next two rules do that...
all-local: boinc$(EXEEXT)

boinc$(EXEEXT): boinc_client$(EXEEXT)
    rm -f boinc$(EXEEXT) .libs/boinc$(EXEEXT)
    $(LN) boinc_client$(EXEEXT) boinc$(EXEEXT)
    if test -f .libs/boinc_client$(EXEEXT) ; then $(LN) .libs/boinc_client$(EXEEXT) .libs/boinc$(EXEEXT) ; fi

install-exec-hook:
    rm -f $(DESTDIR)$(exec_prefix)/bin/boinc$(EXEEXT)
    $(LN) $(DESTDIR)$(exec_prefix)/bin/boinc_client$(EXEEXT) $(DESTDIR)$(exec_prefix)/bin/boinc$(EXEEXT)

## these source files need to be specified because no rule uses them.

EXTRA_DIST = *.h \
    mac \
    translation \
    win

Makefile.curl.am

## -*- mode: make; tab-width: 4 -*-
## $Id$

include $(top_srcdir)/Makefile.incl

# (for a while we used "-static -static-libgcc" on linux, but this is obsolete
# now)
#STATIC_FLAGS=@STATIC_FLAGS@

client-bin: @CLIENT_BIN_FILENAME@

LIBS += @CLIENTLIBS@

bin_PROGRAMS = boinc_client

EXTRA_PROGRAMS = cpu_benchmark

boinc_client_SOURCES = \
    acct_mgr.cpp \
    acct_setup.cpp \
    app.cpp \
    app_control.cpp \
    app_graphics.cpp \
    app_start.cpp \
    check_state.cpp \
    client_msgs.cpp \
    client_state.cpp \
    client_types.cpp \
    cs_account.cpp \
    cs_apps.cpp \
    cs_benchmark.cpp \
    cs_cmdline.cpp \
    cs_data.cpp \
    cs_files.cpp \
    cs_prefs.cpp \
    cs_scheduler.cpp \
    cs_statefile.cpp \
    cs_trickle.cpp \
    dhrystone.cpp \
    dhrystone2.cpp \
    file_names.cpp \
    file_xfer.cpp \
    gui_http.cpp \
    gui_rpc_server.cpp \
    gui_rpc_server_ops.cpp \
    hostinfo_linux.cpp \
    hostinfo_network.cpp \
    hostinfo_unix.cpp \
    http_curl.cpp \
    log_flags.cpp \
    main.cpp \
    net_stats.cpp \
    net_xfer_curl.cpp \
    pers_file_xfer.cpp \
    scheduler_op.cpp \
    time_stats.cpp \
    whetstone.cpp \
    linux/user_idle_time_detection.c

boinc_client_DEPENDENCIES = $(LIBRSA)
boinc_client_CPPFLAGS = -D_USE_CURL -I../../curl-7.14.0/include -I $(srcdir)/win $(AM_CPPFLAGS) -O3
boinc_client_LDFLAGS = -static-libgcc
boinc_client_LDADD = -L/usr/local/ssl/lib -lssl -L../../curl-7.14.0/lib -lcurl -L../lib -lboinc $(RSA_LIBS) $(PTHREAD_LIBS)
#boinc_client_LDFLAGS = $(STATIC_FLAGS)

# the following don't do anything
cpu_benchmark_SOURCES = whetstone.cpp dhrystone.cpp
cpu_benchmark_CFLAGS = -O3 $(AM_CFLAGS)

all-local: client-bin

# make a hard link to the client name.
@CLIENT_BIN_FILENAME@: boinc_client
    rm -f $@
    @LN@ $? $@
    @STRIP@ $@

## these source files need to be specified because no rule uses them.

EXTRA_DIST = *.h \
    mac \
    translation \
    win

clean-local:
    rm -f @CLIENT_BIN_FILENAME@

configure.ac 由于 Stackoverflow 字符数限制,无法在此处插入。

最佳答案

您应该收到警告:

// This is wrong...
extern GDBusProxy* proxy = NULL;
warning: ‘proxy’ initialized and declared ‘extern’
 extern GDBusProxy* proxy = NULL;
                    ^~~~~

The extern storage class specifier basically means "this is defined somewhere else", but the = NULL is not really somewhere else.

Just like functions, with variables you should:

  • Declare them in the header file (compiled many times):

    extern GDBusProxy *proxy;
    

    这是一个声明,您可以根据需要拥有任意多个单个对象的声明(只要它们都兼容)。

  • 在 C 文件中定义它们(编译一次):

    GDBusProxy *proxy = NULL;
    

    这是一个定义,您在整个项目中只能有一个定义。因此它不能出现在头文件中,除非该头文件仅包含在一个 C 文件中。

这不是唯一的方法。您可以在任何地方使用以下声明:

GDBusProxy *proxy;

这是一种特殊情况,它算作一个定义,但您的程序中可以有多个定义。

注意 = NULL 是多余的。默认情况下,全局变量是零初始化的。

关于c++ - GNU 链接器 : errors if pointer in header file is declared NULL and/or extern,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56401181/

相关文章:

c++ - 你能用 BOOST_AUTO 创建一个引用类型吗?

c++ - QT造物主: OpenCV dll lib can not be added ("File format not recognized")

c - 了解指针取消引用和数组索引之间的区别

c++ - 使用 GCC 编译 .CPP

c++ - 在 C++ 源文件中定义链接选项

c++ - 如何在 vc 中停止正在进行的上传

c++ - 为什么 C++ 的 NULL 通常是整数文字而不是像 C 中的指针?

c - 静态分析“指向本地外部范围的指针”——误报?

c - 在其他翻译单元中强制内联功能

c++ - 释放内存映射文件后取消映射 View 是否安全?