- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
以“例如”开头:
libJUMP.so
和 libSIT.so
。 jump()
,类似地 SIT 包含函数 sit()
jump()
功能、sit()
功能,或两者兼而有之。但是,如果可能的话,我想不使用#ifdef
。libJUMP.so
的 header :
#ifndef JUMP_H_
#define JUMP_H_
#define JUMP_ENABLED
void jump();
#endif /* JUMP_H_ */
libSIT.so
的 header :
#ifndef SIT_H_
#define SIT_H_
#define SIT_ENABLED
void sit();
#endif /* SIT_H_ */
我有一个应用程序:
#include "jump.h"
#include "sit.h"
int main()
{
// #ifdef JUMP_ENABLED
jump();
// #endif /* JUMP_ENABLED */
// #ifdef SIT_ENABLED
sit();
// #endif /* SIT_ENABLED */
}
所以:
#ifdef
的方法?有没有更好的方法?
dlopen() 的某种组合
和 dlsym()
?) 任何简单的例子,如果这确实是正确的?如果可能的话,用我上面的代码举例 :D?如果这是一个愚蠢的问题,或者根本不可能,请随时告诉我。如果有类似的问题,这将被视为重复,请告诉我,我将删除此帖子。
最佳答案
考虑这三个文件。首先,jump.c
:
#include <stdio.h>
int jump(const double height)
{
fflush(stdout);
fprintf(stderr, "Jumping %.3g meters.\n", height);
fflush(stderr);
return 0;
}
二、sit.c
:
#include <stdio.h>
int sit(void)
{
fflush(stdout);
fprintf(stderr, "Sitting down.\n");
fflush(stderr);
return 0;
}
第三,example.c
使用上面的一个或两个,这取决于它们是(如 libjump.so
还是 libsit.so
,分别)存在于当前工作目录中:
#include <stdio.h>
#include <dlfcn.h>
static const char *jump_lib_path = "./libjump.so";
static int (*jump)(const double) = NULL;
static const char *sit_lib_path = "./libsit.so";
static int (*sit)(void) = NULL;
static void load_dynamic_libraries(void)
{
void *handle;
handle = dlopen(jump_lib_path, RTLD_NOW | RTLD_LOCAL);
if (handle) {
jump = dlsym(handle, "jump");
/* If no jump symbol, we don't need the library at all. */
if (!jump)
dlclose(handle);
}
handle = dlopen(sit_lib_path, RTLD_NOW | RTLD_LOCAL);
if (handle) {
sit = dlsym(handle, "sit");
/* If no sit symbol, the library is useless. */
if (!sit)
dlclose(handle);
}
}
int main(void)
{
int retval;
load_dynamic_libraries();
if (jump) {
printf("Calling 'jump(2.0)':\n");
retval = jump(2.0);
printf("Returned %d.\n\n", retval);
} else
printf("'jump()' is not available.\n\n");
if (sit) {
printf("Calling 'sit()':\n");
retval = sit();
printf("Returned %d.\n\n", retval);
} else
printf("'sit()' is not available.\n\n");
return 0;
}
让我们首先编译并运行示例程序:
gcc -Wall -O2 example.c -ldl -o example
./example
程序输出 jump() 或 sit() 都不可用。让我们把 jump.c 编译成动态库 libjump.so,然后再次运行示例:
gcc -Wall -O2 -fPIC -shared jump.c -Wl,-soname,libjump.so -o libjump.so
./example
现在,jump() 函数起作用了。让我们也编译 sit.c,并最后一次运行示例:
gcc -Wall -O2 -fPIC -shared jump.c -Wl,-soname,libsit.so -o libsit.so
./example
在这里,两个函数都被调用,一切正常。
在example.c
中,jump
和sit
是函数指针。我们将它们初始化为 NULL,以便我们可以使用 if (jump)
来检查 jump
是否指向一个有效的函数。
load_dynamic_libraries()
函数使用 dlopen()
和 dlsym()
获取函数指针。请注意,如果动态库已成功打开,并且找到了必要的符号,我们不会dlclose()
它,因为我们希望将动态库保留在内存中。 (如果它看起来不是我们想要的那种库,我们只会dlclose()
它。)
如果你想避免 if (jump)
和 if (sit)
子句,你可以使用 stubs like
int unsupported_jump(const double height)
{
return ENOTSUP;
}
int unsupported_sit(void)
{
return ENOTSUP;
}
并且在 load_dynamic_libraries()
的末尾,将函数转移到 stub 而不是 NULL 指针,即
if (!jump)
jump = unsupported_jump;
if (!sit)
sit = unsupported_sit;
请注意,类函数接口(interface)最易于使用,因为函数指针充当有效原型(prototype)。如果您需要对象,我建议使用 getter 函数。只要您记得 dlsym()
返回一个指向对象的指针,对象就可以正常工作;使用 getter 函数,这在 getter 函数指针类型中是显式的。
插件接口(interface)通常只有一个函数(例如,int properties(struct plugin *const props, const int version)
),用于填充函数和对象指针的结构。应用程序提供其使用的结构版本,插件函数返回成功或失败,具体取决于它是否可以填充结构以适应该版本。
由于插件通常存储在单个目录中(/usr/lib/yourapp/plugins/
很常见),您可以使用 opendir()
轻松加载所有插件。和 readdir()
一个一个地扫描插件目录下的文件名,dlopen()
一个一个,获取properties()
函数指针,调用它看看是什么插件提供的服务种类;通常创建插件结构的数组或链接列表。
如您所见,所有这些在 Linux 中都非常非常简单明了。如果你想要一个特定的插件功能示例,我建议你将其作为一个单独的问题提出,并提供更多关于接口(interface)应该公开什么样的功能的细节——确切的数据结构和函数原型(prototype)在很大程度上取决于什么样的我们手头有申请。
有问题吗?评论?
关于c - 如何使用共享对象库来启用/禁用功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28837433/
在gdb中获取此消息。我知道它不是错误或任何东西。我也做了分页,所以那不是问题。 有什么办法可以抑制此消息? 最佳答案 我很好奇看到这个问题没有得到解决... 我获得了GDB manual,它说(部分
好吧,这很烦人,而且可能很简单。我想用禁用的复选框启动我的网页,并在选择列表框中的特定行后启用这些框。所以我把它放在 onload 方法中 onload = function () { for
看来我需要以某种方式在我的 php 页面上禁用 IPv6,但我不确定该怎么做。我想我必须在我的 INI 文件中的某处添加 --disable-ipv6 ……虽然这看起来不像正确的语法。 我正在尝试解决
我有这两个代码: 第一个是禁用复制粘贴的宏: Sub Desable_Copy() Dim oCtrl As Office.CommandBarControl For Each oCt
在下面的代码中,我想, 如果我选择/单击“患者类型”按钮。它们在菜单“xmenumain”“儿科心电图”项中应该被禁用(它应该列在菜单列表中,但颜色为淡灰色)。我如何实现它? void MyMenu:
我目前在 Coordinator 布局中有一个底部导航栏,我向其添加了 HideBottomViewOnScrollBehaviour。有些屏幕需要隐藏导航栏,我可以通过从 BottomNavigat
我需要一些关于 jquery if 条件的帮助。我已经搜索和测试了几个小时,任何帮助都会很棒!我得到这个 HTML 代码: Value: No Match Test Test 2 Test 3
我正在开发 Delphi -7 中的自定义组件我有一些published特性 private { Private declarations } FFolderzip ,Fi
尝试学习菜单处理的基础知识。我的测试应用程序的菜单栏有 3 个菜单——即“TestApp”、“File”和“Help”。我发现我可以完全删除这些菜单,只需调用 say: NSMenu* rootMen
我以编程方式创建一个 NSMenuItem,但它被禁用。如果我重写 validateMenuItem: 方法并为所有项目返回 YES,则菜单项工作正常。 当我告诉菜单 autoEnableItems
我的 Web 表单中有一个 asp 按钮 (runat="server") 进入更新面板。 当我点击这个按钮时,它会执行一些操作。 Private Sub ButtonDoI
我目前正在为 video.js 构建一个插件,它可以在某些断点处将覆盖层呈现在屏幕上。但是,在不启动视频的情况下,我无法单击任何叠加层。我认为我需要禁用播放器上的点击播放功能。 我应该如何禁用/启用
设置剑道网格 selectable: "row", navigatable: true, 允许选择列标题单元格并通过键盘切换其排序状态。如何完全禁用使用键盘选择列标题单元格的功能? 最
我不想卸载code rush。我只是想在不需要的时候有机会将其关闭。 这可能吗? (快速版本)... 最佳答案 首先您应该打开“DevExpress”菜单。默认情况下,它在 CodeRush Xpre
设置: 我正在使用 TinyMCE 的 Angular 包装器来允许我的用户构建自己的电子邮件模板。这些电子邮件会发送给每个用户组织内的多个人员。我创建了自定义工具栏按钮来插入小文本 block [[
我希望下拉菜单在悬停时打开,前提是窗口大于 767 像素。我试图在页面加载和窗口调整大小时调用一个函数,并使用宽度大小条件。 enableHover() 函数仅适用于页面加载,不适用于窗口调整大小。
由于我遇到了一些问题,我正在 .NET Framework 4 中尝试连接池。使用 SQL Profiler,我可以看到每次从连接池中获取连接时,都会执行存储过程 sp_reset_connectio
我避免在我的 swift 代码中收到警告。然而,当谈到 Storyboard要求时,这对我来说有点困难。 所以现在我只想禁用 xcode 显示有关 Storyboard问题的警告。 我尝试了以下方法但
我不是 JavaScript 专家,我目前正在尝试为表单创建一个函数,该函数根据上一页上选择的数字重复相同的字段。 表单字段可能有 1 到 10 行,每行都有一个单选按钮选择,可启用/禁用每一行。 目
我正在尝试使用 CPU2006 运行各种基准测试,以查看各种优化在 gcc 速度方面的作用。我熟悉 -O1、-O2 和 -O3,但听说 -msse 是一个不错的优化。 -msse 到底是什么?我还看到
我是一名优秀的程序员,十分优秀!