2013-03-13 69 views
1

我有用C编写的科学模拟代码,它从命令行运行。用户在model.c文件中将输入模型作为一组C子程序提供,然后在运行时将其编译为代码。有条件的编译/用gcc链接

某些模型属性并不总是与特定问题相关,但目前用户仍然需要为该属性提供一个空的虚拟函数以便代码进行编译。

只有当用户提供的model.c不包含该属性的子例程时,是否可以为源代码中嵌入的模型属性设置虚拟子例程?

作为一个例子,如果model.c包含一个称为temperature()子程序中,代码应该链接到的那一个,而不是称为temperature()子程序中src/dummy_function.c找到。如果model.c没有temperature(),则编译器应使用src/dummy_function.c中的虚拟函数。

如果可能,我宁愿在model.c文件中不要求预处理器指令的解决方案。

+0

使用C++类和继承怎么样?您可以创建一个父类,将所有函数实现为假。然后每个想使用函数的人都可以在派生类中简单地覆盖它。 – Nippey

+0

这确实是一种选择。然而,用C++重新实现整个代码将是一项重大的努力。我希望有一个简单的解决方案,不需要重新设计代码。 –

+0

如何使用'dummy_function.c',将其重命名为'main.c'并将其提供给用户?想要使用函数的用户可以用真实函数替换该虚拟函数。 – Beta

回答

4

是的,你可以。假设你在文件中有简单的代码,说undesym.c:

int 
main(void) 
{ 
    user_routine(); 
    return 0; 
} 

创建发言权文件fakeone.c弱存根

#include "assert.h" 

int __attribute__((weak)) 
user_routine(void) 
{ 
    assert(0 == "stub user_routine is not for call"); 
    return 0; 
} 

现在创建 “用户” 功能,说goodone.c

#include "stdio.h" 

int 
user_routine(void) 
{ 
    printf("user_routine Ok\n"); 
    return 0; 
} 

现在,如果你将连接在一起gcc undesym.c fakeone.c那么a.out的运行断言,但如果你将添加到goodone.c编译,就像gcc undesym.c fakeone.c goodone.c,那么它会倾向于强烈的定义为弱,并会运行到消息。

您可能采用相同的机制,定义弱的默认功能。

+0

这是完美的!非常感谢。 –

+0

好的。不知道。 +1 – Nippey

0

既然您说用户的子例程“在运行时编译到代码中”,那么可以使用动态链接来加载用户提供的二进制文件并在运行时查找它们的入口点。在Linux(或任何POSIX系统),这将是基于dlopen()/dlsym(),并期待或多或少是这样的:

#include <dlfcn.h> 

/* ... */ 

/* Link the UserModule.so into the executable */ 
void *user_module = dlopen("UserModule.so", RTLD_NOW); 

if (!user_module) { 
    /* Module could not be loaded, handle error */ 
} 

/* Locate the "temperature" function */ 
void *temperature_ptr = dlsym(user_module, "temperature"): 

if (!temperature_ptr) { 
    /* Module does not define the "temperature" function */ 
} 

void (*user_temperature)() = (void(*)())temperature_ptr; 

/* Call the user function */ 
user_temperature(); 

dlopen documentation了解详情。在您使用的任何操作系统中都可能使用类似的工具。