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

时间:2022-06-29 21:44:49

I have a problem when using WEAK reference in C. Make assumption, I have the src code structure as follows:

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

//Eclipse C project structure

// 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

And:

和:

//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

//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

//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

//dummy_TestWeakAttribute.h

#define static //disable static keyword

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

//weak_test_case.c

//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

//strong_test_case.c

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

void test_function_strong(void){
    function();
}

I got the result on the screen:

我在屏幕上得到了结果:

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

I can't use the REAL function anymore. All my making calls to the real test function is impossible because it was declared as __attribute__((weak)) before. So, Is there anybody having idea on this case ? The main purpose, I'd like to call my real test (in source_sample.c) but don't remove weak attribute as well.

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

1 个解决方案

#1


2  

First off, be aware that weak linkage is not a C concept. It is an ELF concept, at least for our purposes, and GCC (and other compiler) support for it is a C extension. Therefore, little of what I have to say is based on the C standard. With that said ...

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

Your program has two functions test(), both with weak linkage. If there were an alternative with strong linkage then that would override both. Since there is not, it is unspecified which of the two is linked to any given reference (call), but it follows from the mechanism of ELF dynamic linking that the same one would would be linked to every reference in any given dynamic object.

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

Other than system libraries, you have only one dynamic object in play -- the program -- so it stands to reason that the same implementation of test() is called at every point. It's unclear to me why you suppose it would be otherwise. Note in particular that the weird games you are playing with the static keyword are strictly obfuscatory. You have no actual static declarations anywhere in the code you present.

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

You indeed could declare a static function test in some file, and in that case you would expect calls to test() from within that file to be linked to the internal static version. To the best of my knowledge, however, a static function cannot also be weak. That wouldn't make any sense.

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

The main purpose, I'd like to call my real test (in source_sample.c) but don't remove weak attribute as well.

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

So you want to provide for overriding some references to the function but not others? Are you nuts? What a nightmare that would be to build, and I don't even want to think about maintaining it.

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

If you want to provide a default implementation that you can always call then you cannot make that the weak function. Doing so is inconsistent with always being able to call it. You can, however, make it a separate, ordinary function that the weak one calls, and any other function also can call:

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

test.h:

#ifndef TEST_H
#define TEST_H

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

#endif

test.c:

#include "test.h"

void test_default(void) {
    printf("I am the default implementation");
}

void test(void) {
    test_default();
}

Anyone with access to test_default() can then call it, but whether it gets called as a result of calling test() depends on what version of test() is linked to the call -- it is weak, so a different version could be provided.

任何有权访问test_default()的人都可以调用它,但是它是否因调用test()而被调用取决于test()的哪个版本与调用相关联 - 它很弱,所以不同的版本可能是提供。

Note also that depending on the scope you want test_default() to have, it might be both possible and sensible to make it static, whereas test() must not be static as long as it is weak.

另请注意,根据您希望test_default()具有的范围,将其设置为静态可能既合乎又合理,而test()只要它很弱就不能是静态的。

#1


2  

First off, be aware that weak linkage is not a C concept. It is an ELF concept, at least for our purposes, and GCC (and other compiler) support for it is a C extension. Therefore, little of what I have to say is based on the C standard. With that said ...

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

Your program has two functions test(), both with weak linkage. If there were an alternative with strong linkage then that would override both. Since there is not, it is unspecified which of the two is linked to any given reference (call), but it follows from the mechanism of ELF dynamic linking that the same one would would be linked to every reference in any given dynamic object.

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

Other than system libraries, you have only one dynamic object in play -- the program -- so it stands to reason that the same implementation of test() is called at every point. It's unclear to me why you suppose it would be otherwise. Note in particular that the weird games you are playing with the static keyword are strictly obfuscatory. You have no actual static declarations anywhere in the code you present.

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

You indeed could declare a static function test in some file, and in that case you would expect calls to test() from within that file to be linked to the internal static version. To the best of my knowledge, however, a static function cannot also be weak. That wouldn't make any sense.

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

The main purpose, I'd like to call my real test (in source_sample.c) but don't remove weak attribute as well.

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

So you want to provide for overriding some references to the function but not others? Are you nuts? What a nightmare that would be to build, and I don't even want to think about maintaining it.

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

If you want to provide a default implementation that you can always call then you cannot make that the weak function. Doing so is inconsistent with always being able to call it. You can, however, make it a separate, ordinary function that the weak one calls, and any other function also can call:

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

test.h:

#ifndef TEST_H
#define TEST_H

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

#endif

test.c:

#include "test.h"

void test_default(void) {
    printf("I am the default implementation");
}

void test(void) {
    test_default();
}

Anyone with access to test_default() can then call it, but whether it gets called as a result of calling test() depends on what version of test() is linked to the call -- it is weak, so a different version could be provided.

任何有权访问test_default()的人都可以调用它,但是它是否因调用test()而被调用取决于test()的哪个版本与调用相关联 - 它很弱,所以不同的版本可能是提供。

Note also that depending on the scope you want test_default() to have, it might be both possible and sensible to make it static, whereas test() must not be static as long as it is weak.

另请注意,根据您希望test_default()具有的范围,将其设置为静态可能既合乎又合理,而test()只要它很弱就不能是静态的。