如果在C中声明为WEAK函数,如何使用REAL函数?

时间:2016-04-13 04:13:49

标签: c elf weak-linking

在C中使用WEAK引用时遇到问题。假设,我的src代码结构如下:

// Eclipse C项目结构

    drv
     |   dummy      
     |     |  dummy_Test.h
     |     |  dummy_TestWeakAttribute.h
     |   src
     |     |  source_sample.c
     |   test
     |     |  myModules
     |             strong_test_case.c
     |             weak_test_case.c
    test_program.c

// test_program.c

#include "drv/dummy/dummy_TestWeakAttribute.h"
#include "drv/dummy/dummy_Test.h"

int main() {
    printf("===================\n");
    printf("  Welcome to main  \n");
    printf("===================\n");
                            // Expectation
    test();                 //-->real function
    function();             //-->real function
    test_function_strong(); //-->real function
    test_function_weak();   //-->weak function

    return 0;
}

// source_sample.c

#include "../dummy/dummy_TestWeakAttribute.h"
#include "../dummy/dummy_Test.h"

static void test(void) {
    printf("NOT overridden!\n");
}

static void function(void){

    int a =1;
    a++;
    test();
}

// dummy_Test.h

#ifndef DRV_DUMMY_DUMMY_TEST_H_
#define DRV_DUMMY_DUMMY_TEST_H_

#define static
//definitions

//struct definitions

//dummy functions

static void test(void);
static void function(void);

//global variable definitions

#endif /* DRV_DUMMY_DUMMY_TEST_H_ */

// dummy_TestWeakAttribute.h

#define static //disable static keyword

static void __attribute__((weak)) test(void);

// weak_test_case.c

#include "../../dummy/dummy_TestWeakAttribute.h"
#include "../../dummy/dummy_Test.h"

static void test(void){
    printf("overridden successfully!\n");
}

void test_function_weak(void){
    function();
}

// strong_test_case.c

#include "../../dummy/dummy_Test.h"

void test_function_strong(void){
    function();
}

我在屏幕上得到了结果:

===================
  Welcome to main  
===================
overridden successfully!
overridden successfully!
overridden successfully!
overridden successfully!

我不能再使用REAL功能了。所有我对真实test函数的调用都是不可能的,因为它之前被声明为__attribute__((weak))。那么,有没有人对此案有所了解?主要目的是,我想调用我的真实testsource_sample.c},但也不要删除 weak属性。

1 个答案:

答案 0 :(得分:2)

首先,要注意弱连接不是C概念。这是一个ELF概念,至少对于我们的目的而言,GCC(和其他编译器)对它的支持是C扩展。因此,我所说的很少是基于C标准。随着那说......

您的程序有两个函数test(),两者都具有弱链接。如果有一个具有强联系的替代方案,那么这将覆盖两者。由于没有,因此未指定哪两个链接到任何给定的引用(调用),但是它遵循ELF动态链接的机制,相同的机制将链接到任何给定动态对象中的每个引用。 / p>

除了系统库之外,你只有一个动态对象 - 程序 - 因此可以确保在每个点调用test()的相同实现。我不清楚为什么你认为不然。请特别注意,您使用static关键字进行的奇怪游戏是严格混淆的。您所提供的代码中的任何位置都没有实际的static声明。

您确实可以在某个文件中声明static函数test,在这种情况下,您希望从该文件中调用test()链接到内部{{1}版本。然而,据我所知,static函数也不能弱。这没有任何意义。

  

主要目的是,我想调用我的真实测试(在source_sample.c中),但也不要删除弱属性。

所以你想提供覆盖一些函数的引用而不是其他的引用?你疯了吗?这将构成一场噩梦,我甚至不想考虑维持它。

如果您想提供一个可以随时调用的默认实现,那么您无法将其作为弱函数。这样做与始终能够调用它不一致。但是,你可以将它作为一个单独的普通函数,弱函数调用,任何其他函数也可以调用:

test.h:

static

test.c的:

#ifndef TEST_H
#define TEST_H

void test(void) __attribute__((weak));
void test_default(void);

#endif

有权访问#include "test.h" void test_default(void) { printf("I am the default implementation"); } void test(void) { test_default(); } 的任何人都可以调用它,但调用test_default()后是否会调用它取决于test()与该调用的链接版本 - 它很弱,所以可以提供不同的版本。

另请注意,根据您希望test()拥有的范围,使test_default()成为可能和明智,而static不得为test()只要它很弱。