通过函数指针使用其他 C 文件中的函数

Use function from other C file by a function pointer

提问人:Sespaetzlean 提问时间:5/21/2023 最后编辑:Sespaetzlean 更新时间:5/23/2023 访问量:162

问:

首先,我不确定标题是否很好地描述了问题,可以随意更改或建议更合适的标题。

我有以下问题: 我需要将函数指针传递给某个结构。当我在同一文件中定义函数时,这工作得很好。看这里:

static void a_func(int param1, /*...*/) {
    //...
}

static const struct bt_mesh_handlers my_handlers = {
    .set = a_func,
    // ...
};

当我现在在另一个文件中定义此函数时,我无法让它工作: 头文件(此处未显示包括防护):

//function declaration:
void a_func(int param1, /*...*/);

C 文件:

//function definition (this was defined wrongly as static before)
void a_func(int param1, /*...*/) {
    //...
}

在主文件中:

#include "myheader.h"

static const struct bt_mesh_handlers my_handlers = {
    .set = a_func,
    // ...
};

当我将函数外包给另一个文件时,我在构建过程中出现以下错误:

未定义对“a_func”的引用

我已经做了一些研究,我比较确定在定义a_func的文件中,会自动生成一个同名的函数指针。因此,我可以使用该指针将我的函数移交给结构体。

但是我不知道如何将该函数指针从外包文件获取到我的主文件中。 一个好的解决方案会是什么样子?

c 静态 指针 函数 定义 联动

评论

0赞 Sespaetzlean 5/22/2023
感谢您的提示,您是绝对正确的。我现在在我的问题中解决了这个问题

答:

1赞 Vlad from Moscow 5/21/2023 #1

静态函数应在使用静态函数的每个翻译单元中定义,因为它具有内部链接。因此,在您的示例中,函数未定义,main

要么在标头中定义它(例如,您可以将其定义为内联函数),要么删除存储类说明符以使函数具有外部链接。static

评论

0赞 nicomp 5/21/2023
不是原始问题的答案。
0赞 Sespaetzlean 5/22/2023
谢谢你的帮助。你是对的,我错误地将静态关键字放在我的问题中(现在已修复在问题:)中)
1赞 Eric Postpischil 5/21/2023 #2

从 的声明中删除 ,包括其定义。statica_func

在此上下文中,赋予标识符内部链接,这意味着名称的使用将仅链接到同一翻译单元(正在编译的源文件,包括它直接或间接包含的所有文件)中的名称定义。statica_func

要链接到另一个翻译单元中定义的名称,您需要外部链接。这是函数的默认设置,因此删除将为您提供外部链接。static

我已经做了一些研究,我比较确定在定义a_func的文件中,会自动生成一个同名的函数指针。

函数的名称是指函数。它指定函数。在 C 中,函数指示符会自动转换为指向函数的指针,除非它是 的操作数或一元。在定义该指针的文件中,没有与函数同名的函数指针的特殊或单独的“生成”。编译器、链接器和/或程序加载程序协同工作,以了解函数的位置,并生成适当的指令来使用该函数或提供其地址。sizeof&

评论

0赞 Sespaetzlean 5/22/2023
正如我在其他问题中已经说过的,我错误地将静态放在这里(当我测试时我没有使用它)。不幸的是,它仍然没有建立起来。非常感谢您对指示符转换为指针的精彩解释,这已经解释了很多。但正如我现在假设的那样,这个指示符/指针似乎只在文件本身中看到,而不是在包含头文件中的文件中看到。那么有没有办法让它对外部文件也可见呢?或者还有什么问题?我的文件仍然没有构建,我收到同样的错误:/
0赞 Eric Postpischil 5/22/2023
@Sespaetzlean:显示确切的错误消息和用于链接程序的命令。
0赞 Sespaetzlean 5/22/2023
我正在使用 nRF Connect 进行构建。命令应该是这样的:west build ... .(我只是在 nRF 连接扩展中点击了 VS 代码中的构建按钮)我收到以下错误:d:/ncs/toolchains/v2.3.0/opt/zephyr-sdk/arm-zephyr-eabi/bin/.。/lib/gcc/arm-zephyr-eabi/12.1.0/../../../../arm-zephyr-eabi/bin/ld.exe:app/libapp.a(model_handler.c.obj):(.rodata.lvl_handlers+0x0):对“a_func”的未定义引用
0赞 Eric Postpischil 5/22/2023
您需要从构建日志中挖掘实际的链接命令,或者找出构建设置中的问题。一个可能的原因是您的项目没有将所有对象模块链接到一个程序中。
0赞 Sespaetzlean 5/23/2023
我做了一些研究,我的文件没有正确链接。感谢您的帮助,我认为这是一个可见性问题:)
0赞 Sespaetzlean 5/23/2023 #3

总结一下:问题是我的文件没有正确链接。 可以从不同的文件调用函数并使用其指针 (一开始对我不起作用)。 埃里克(Eric)通过指示符很好地解释了这是如何工作的。