I am developing a shared library on Linux in C using GCC. I noticed that any function in the shared library can be overridden by redefining it in the main application. Is there a way to prevent specific functions from being overridden in a shared library?
If you don't need to export that function to the world, make it static
static void a() {
}
void b() {
a();
}
the main application will have no way to directly call a, but maybe you don't need that.
If you want to also export that function the the world, you could do:
static void real_a() {
/* the actual implementation */
}
void a() { /* wrapper for export */
real_a();
}
void b() { /* your library code has to call the real function */
...
real_a();
}
The main application can still override a, but that does not influence the library code, which is calling real_a internally.
Related
Given a C library (liblegacy.a) that contains:
function_legacy1()
function_legacy2()
function_legacy3()
...
function_legacy500()
and a C binary (mybin) which links against liblegacy.a:
function_binary1() {
function_legacy1();
function_legacy2();
function_legacy3();
}
function_binary200() {
function_legacy500();
}
and mybin is partially tested with Google Test framework (in progress).
The technical debt is high and it will be a big work to test mybin and/or liblegacy.a.
As a step to remove this debt, I like to start implementing a test for function_binary1 without impacting the rest. My idea would be to mock only the 3 functions used by it (function_legacy1, function_legacy2, function_legacy3) and keep linking against the lib so that I don't have to split the .c/.h files to have only the interesting part in the translation unit.
A first approach would probably to make a dynamic shared library that contains the 3 functions, and use LD_PRELOAD to override these ones at runtime.
Since I'm new with GMock, maybe we can do that in a better way directly with this framework.
Is is possible to mock only some functions of an external lib with GMock to avoid refactoring in this case?
Note: This question is somehow related to, but answers are not very clear to me
Can gmock be used for stubbing C functions?
You might run into problems if you are working with a static library
(liblegacy.a) and a shared library libmock.so (libmock.dylib on
macOS) and if any of the mocked functions is defined in an object file
that also contains an unmocked function.
For example, if you mock function_legacy1() but in liblegacy.a it is
defined in the same object file as function_legacy2(), you might run
into linking conflicts with function_legacy1() being multiply defined,
or you might run into the wrong code being executed at runtime.
Consider the following setup:
legacy.h — declares the legacy functions.
legacy_1_2.c — defines function_legacy1() and function_legacy2().
legacy_3_4.c — defines function_legacy3() and function_legacy4().
mock_1.c — defines function_legacy1().
mock_2.c — defines function_legacy2().
testprog1.c — defines a main() function that calls each of the legacy functions.
testprog2.c — a copy of testprog1.c.
Each of the legacy functions in each source file is the same apart from the name:
void function_legacy1(void)
{
printf("%s:%d:%s()\n", __FILE__, __LINE__, __func__);
}
The main() program looks like:
#include "legacy.h"
#include <stdio.h>
int main(void)
{
printf("%s:%d:%s()\n", __FILE__, __LINE__, __func__);
function_legacy1();
function_legacy2();
function_legacy3();
function_legacy4();
printf("%s:%d:%s()\n", __FILE__, __LINE__, __func__);
return 0;
}
The code can be compiled and run as shown below:
$ gcc -shared -o libmock1.dylib mock_1.c
$ gcc -shared -o libmock2.dylib mock_1.c mock_2.c
$ gcc -o testprog1 testprog1.c -L. -lmock1 -llegacy
$ gcc -o testprog2 testprog2.c -L. -lmock2 -llegacy
$ testprog1
testprog1.c:6:main()
legacy_1_2.c:6:function_legacy1()
legacy_1_2.c:11:function_legacy2()
legacy_3_4.c:6:function_legacy3()
legacy_3_4.c:11:function_legacy4()
testprog1.c:11:main()
$ testprog2
testprog2.c:6:main()
mock_1.c:6:function_legacy1()
mock_2.c:6:function_legacy2()
legacy_3_4.c:6:function_legacy3()
legacy_3_4.c:11:function_legacy4()
testprog2.c:11:main()
$
As you can see, there are no problems linking.
However, testprog1 is linked with a mock library that only includes a
mock for function_legacy1(), and it doesn't see the mocked version of
function_legacy1().
By contrast, testprog2 is linked with a mock library that includes a
mock for function_legacy1() and function_legacy2() and it does see
both the mocked functions.
YMMV on a Linux system, or other non-macOS systems.
Thus, your mocking may or may not work if the legacy functions are defined
several per object file in the static library.
Sounds like you want to conditionally delegate some functions to the real implementation (function_legacy1, function_legacy2, function_legacy3) and the rest to the mock.
I think you should be able to use this recipe.
For mocking stand-alone functions such as function_legacy1, you probably need to wrap them inside a virtual class first. Something like this:
class LegacyInterface {
public:
...
virtual bool function_legacy1(int p) = 0;
virtual bool function_legacy2(int p) = 0;
...
virtual bool function_legacyn(int p) = 0;
};
// This should be used in production.
class LegacyProduction : public LegacyInterface {
public:
bool function_legacy1(int p) override {
return ::function_legacy1(p); // Calling the real function_legacy1
}
bool function_legacy2(int p) override {
return ::function_legacy2(p); // Calling the real function_legacy2
}
...
bool function_legacyn(int p) override {
return ::function_legacyn(p); // Calling the real function_legacyn
}
};
// This should be used in test.
class LegacyMock : public LegacyInterface {
public:
// Normal mock method definitions using gMock.
MOCK_METHOD(bool, function_legacy1, (int p), (override));
MOCK_METHOD(bool, function_legacy2, (int p), (override));
...
MOCK_METHOD(bool, function_legacyn, (int p), (override));
// Delegates the default actions of function_legacy500 to the real implementation.
void Delegate500ToReal() {
ON_CALL(*this, function_legacy500).WillByDefault([this](int n) {
return ::function_legacy500(n); // Calling the real function_legacy500
});
}
};
Now you should change your code to use the wrapper class:
function_binary1(LegacyInterface *legacy_wrapper) {
legacy_wrapper->function_legacy1();
legacy_wrapper->function_legacy2();
legacy_wrapper->function_legacy3();
}
function_binary200(LegacyInterface *legacy_wrapper) {
legacy_wrapper->function_legacy500();
}
where you initialize legacy_wrapper for test:
LegacyInterface *legacy_wrapper = new LegacyMock;
And for production:
LegacyInterface *legacy_wrapper = new LegacyProduction;
So your test would be:
TEST(LegacyTest, function_binary1) {
LegacyMock legacy_wrapper;
EXPECT_CALL(foo, function_binary1(_));
EXPECT_CALL(foo, function_binary2(_));
EXPECT_CALL(foo, function_binary3(_));
// Assert
EXPECT_EQ(function_binary1(&legacy_wrapper), ...);
}
TEST(LegacyTest, function_binary200) {
LegacyMock legacy_wrapper;
legacy_wrapper.Delegate500ToReal();
// No action specified, meaning to use the default action, which is calling the real function_legacy500.
EXPECT_CALL(foo, function_legacy500(_));
// Assert
EXPECT_EQ(function_binary200(), ...);
}
The above code can still be linked against the legacy lib as was before.
I know its basic but I am not familiar with C and I couldn't understand the answers here in the subject .
Inside a C file I have this functions :
void uart_event_handle(app_uart_evt_t * p_event)
{
}
static void uart_init(void)
{
}
void initialize()
{
uart_init();
}
The static function uart_init() was inside some example program main.c , i am trying to put it inside another C file ( this one)
The error occurs only when I call : uart_init(); . Otherwise it will not happen.
Declaring a function static makes it invisible outside the translation unit. This is similar to declaring fields private in a class, because static "hides" the function from all other files.
This lets you define a new function with the same name in some other file without worrying about name collisions. At the same time, static makes it impossible to call the function from outside the .c file where it is defined.
Your example provides a use case for making static functions: initialize becomes part of the "public" interface of the library, while uart_init remains hidden.
How do I pass a delegate to an external C function taking a function pointer, in D?
Let me cross post what I said on the newsgroup:
How do I pass a delegate to an external C function taking a
function pointer?
You can't do it directly in general, unless you can modify the C
function, then you can hack around it, but a delegate and a
regular function pointer are pretty different animals.
But perhaps you can magic hack it. Observe:
// a C function that needs a plain function
extern(C) void test(void function() f) {
// pretend this is implemented in C
f();
}
// just create a random delegate
void delegate() foo(int a) {
return { import std.stdio; writeln(a); };
}
// what we want to work
void main() {
auto dg = foo(10);
dg(); // works
//test(dg); // won't work
test(bindDelegate(dg)); // we want this
}
// transform delegate into pointer..
import std.traits;
auto bindDelegate(T, string file = __FILE__, size_t line = __LINE__)(T t) if(isDelegate!T) {
static T dg;
dg = t;
extern(C)
static ReturnType!T func(ParameterTypeTuple!T args) {
return dg(args);
}
return &func;
}
What bindDelegate does is create a special static variable and
function for that specific call. It is as if we wrote a separate
function and global to hold it.
The __FILE__, __LINE__ things are a filthy hack to make it
instantiate a separate variable+function pair for different
lines so the global variable holding the delegate won't be so
easily overwritten.
I have a callback inside a C DLL (static void __stdcall) . I want another program to register it as such (by passing it the func ptr) and then call the calback inside the DLL. I have had no luck so far. However, the same callback works if its inside a regular C++ program. I am now wondering if having callbacks in a DLL is even possible. Any help will be appreciated!
Thanks.
Adding some code:
C# app:
[DllImport("DLLfilename.dll")]
public static extern void DLL_SetCallback(CallbackDelegate pfn);
public delegate void CallbackDelegate();
//setDelegate() is called in init() of the C# app
public void setDelegate()
{
CallbackDelegate CallbackDelegateInstance = new CallbackDelegate(callback);
DLL_SetCallback(CallbackDelegateInstance);
}
public void callback()
{
//This is the function which will be called by the DLL
MessageBox.Show("Called from the DLL..");
}
C DLL:
//is linked to externalLibrary.lib
#include "externalLibrary.h"
typedef void (__stdcall CallbackFunc)(void);
CallbackFunc* func; //global in DLL
//Exported
extern "C" __declspec(dllexport) void DLL_SetCallback(CallbackFunc* funcptr)
{
//setting the function pointer
func = funcptr;
return;
}
//Exported
extern "C" __declspec(dllexport) void RegisterEventHandler(Target, Stream,&ProcessEvent , NULL)
{
//ProcessEvent is func to be caled by 3rd party callback
//Call third-party function to register &ProcessEvent func-ptr (succeeds)
...
return;
}
//This is the function which never gets called from the 3rd party callback
//But gets called when all the code in the DLL is moved to a standard C program.
void __stdcall ProcessEvent (params..)
{
//Do some work..
func(); //Call the C# callback now
return;
}
Your question is a little confusing. Are you saying that you have a non-exported function within a DLL, which you wish to take the address of and pass to some external code, which will call it back? That's perfectly reasonable to do. If it's not working, here are the things to look at.
1) Make sure that the calling convention is correct on the definition of the function, the type of the function pointer within your DLL, and the type of the function pointer as declared in the external code.
2) Within your DLL, attempt to call the callback through the same function pointer that you're passing to the external code.
3) If (1) is correct, and (2) works, then fire up your debugger, put a breakpoint on the line where you're trying to call the callback from external code, and then drop into disassembly. Step through the call and see where it ends up.
Hello. I am trying to make a fully thread-safe initialization function for my library and I couldn't easily find an alternative to pthread_once, which should solve the problem very easily. I've come to this code:
void libInit (void)
{
#ifdef WIN32
static volatile int initialized = 0;
static HANDLE mtx;
if (!initialized)
{
if (!mtx)
{
HANDLE mymtx;
mymtx = CreateMutex(NULL, 0, NULL);
if (InterlockedCompareExchangePointer(&mtx, mymtx, NULL) != NULL)
CloseHandle(mymtx);
}
WaitForSingleObject(mtx);
if (!initialized)
{
libInitInternal();
initialized = 1;
}
ReleaseMutex(mtx);
}
#else
static pthread_once_t initialized = PTHREAD_ONCE_INIT;
pthread_once(&initialized, libInitInternal);
#endif
}
The libInitInternal() call leads to a thread-unsafe function, that initializes the library.
I would like to hear any suggestions on what I could be doing wrong or whether you know about a better solution.
I think you want to use the One-Time Initialization functionality. In synchronous mode, all threads block until the first thread to call it completes. Seems analogous to pthread_once().
There is sample code here.
So in your case, you would say:
BOOL CALLBACK CallLibInitInternal(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContex) {
libInitInternal();
return TRUE;
}
void libInit() {
#ifdef WIN32
static INIT_ONCE s_init_once;
InitOnceExecuteOnce(&s_init_once, CallLibInitInternal, NULL, NULL);
#else
...
#endif
}
You might want to check what pthreads-win32 does in its pthread_once() implementaion. or just use that, if that proves to be easier.
After looking at the following source code for pthread_once() (from here), It looks like you're on the right track.
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
/* Check first for speed */
if (once_control->state == PTHREAD_NEEDS_INIT) {
pthread_mutex_lock(&(once_control->mutex));
if (once_control->state == PTHREAD_NEEDS_INIT) {
init_routine();
once_control->state = PTHREAD_DONE_INIT;
}
pthread_mutex_unlock(&(once_control->mutex));
}
return(OK);
}
btw, I'll be using pthread_once() to replace some rather convoluted functions in my code.
When using GCC or clang, you can use constructor and destructor attributes. These work for both shared and static libraries, and execute code before and after main is run, respectively. Additionally, you can specify multiple constructor and destructor functions. Much cleaner than the singleton approach, and doesn't require you to remember to call libInit() from your main().
static void __attribute__((constructor))
your_lib_init(void)
{
fprintf(stderr, "library init\n");
}
static void __attribute__((destructor))
vensim_ctx_destroy(void)
{
fprintf(stderr, "library destroy\n");
}
I would check out this article. It is a solution for C++ singletons, but I believe you can use the solution for your code as well: http://www.ddj.com/cpp/199203083?pgno=1
Sadly the listing for the QLock itself is missing, it looks as if they are trying to sell the CD, but there appears to be enough description of it to write one yourself.