0

I am compiling with g ++ an application that calls some functions defined in a "C" library. Some of the functions that I need to call are defined as static in the original ".c" file (I know that when a function is defined static it is so that it is not called from outside of that file, but despite that, I need to call them from outside of the same).

I am going to execute them from outside that file using pointers to functions and to see how they work, I have prepared this example, where I want to execute in file_2.c the static functions fun5 and fun6 defined in file_1.c

file_1.h
--------
#ifndef FILE_1_H
#define FILE_1_H

int (*getPtrFun6(void*))(int,char,char*);

#endif
file_1.c
--------
#include <stdio.h>

int(*ptr_fun5)(int,int);

static int fun5(int p1, int p2)
{
  printf("fun5 called.\n");
  ptr_fun5 = &fun5;

  return p1 + p2;
}

static int fun6(int p1, char p2, char* p3)
{
  printf("fun6 called with p1 = %d, p2 = %c, p3 = %s.\n", p1, p2, p3);
  return p1;
}

int (*getPtrFun6(void*))(int,char,char*)
{
  return fun6;
}
file_2.c
--------
#include <stdio.h>
#include <cstring>
#include "file_1.h"

extern int(*ptr_fun5)(int,int);
extern int(*ptr_fun6)(int,char,char*);

int main(void)
{
  int returnValue = 0;

  // To run fun5
  returnValue = (ptr_fun5)(15, 32);
  printf ("Returns %d\n", returnValue);

  // To run fun6
  char myString[50];
  memset(myString,0,50);
  strncpy(myString,"THIS IS OK",10);
  ptr_fun6 = getPtrFun6();  
  returnValue = (ptr_fun6)(32, 'v', myString);
  printf ("Returns %d\n", returnValue);

  return 0;  
}

I compile the program with the command:

g++ file_2.c file_1.c -o static_example

As you can see from the source code, I have tried two different ways to use a pointer to a static function.

If I comment on everything about fun6 in the source code, compile it and run it (just call fun5) I get the error "Segmentation fault".

On the other hand, if I comment on everything related to fun5 in the source code and leave only fun6, when compiling the program, I get these errors:

file_2.c: In function ‘int main()’:
file_2.c:20:25: error: too few arguments to function ‘int (* getPtrFun6(void*))(int, char, char*)’
   ptr_fun6 = getPtrFun6();
                         ^
In file included from file_2.c:4:
file_1.h:4:7: note: declared here
 int (*getPtrFun6(void*))(int,char,char*);
       ^~~~~~~~~~

I have looked at various forums and tutorials on the web and I don't see what the error is, so I would need some help on the correct way to use the pointers to fun5 and fun6.

8
  • 1
    And when you used your debugger to run your program step by step, one line at a time, what did your debugger show you? Commented Aug 19, 2021 at 10:40
  • If a function is static then it is NOT meant to be called from any other unit of compilation. It is local to that file. If you need to call this function in some other unit of compilation, you simply need to remove the static keyword and let it have external linkage. This whole pointer business looks horrendous Commented Aug 19, 2021 at 10:47
  • 4
    That's a bit too broad, @MoNazemi. Calling a static function from a different compilation unit via a function pointer is allowed, and it has a few reasonable use cases. Of course it's not what one ordinarily should do, but the static is technically about linkage of the function identifier, and only indirectly about from where it can be called. Commented Aug 19, 2021 at 10:51
  • 1
    @MoNazemi In this case yes the globals is very bad design. But generally speaking, there are situations where returning a function pointer to an internal implementation is a good idea. That's one way of private encapsulation. Commented Aug 19, 2021 at 10:51
  • 1
    By the way, you seem to be compiling these files as C++, judging by the #include <cstring>. If you have a compiler that supports C properly, you may want to change that to #include <string.h> and ensure your compiler is compiling as C, not C++. There are differences between the two languages, and compiling C source code as C++ can create confusion while learning. Commented Aug 19, 2021 at 10:57

3 Answers 3

2

(just call fun5) I get the error "Segmentation fault".

Because fun5 is uninitialized, it doesn't point anywhere.

when compiling the program, I get these errors: ... error: too few arguments to function

So why did you declare it to take a void* as parameter? If you don't want that, then it should be void.


General advise:

  • Get rid of global variables with extern.
  • Use typedef whenever dealing with function pointers, so that the code can be read by humans. Evidentally, int (*getPtrFun6(void*))(int,char,char*) isn't readable even by yourself.
Sign up to request clarification or add additional context in comments.

Comments

2
int (*getPtrFun6(void*))(int,char,char*);

Confusing syntax is leading to wrong prototype and declaration.

The easy to read way (function pointers are same as "normal" pointers):

typedef int fun6type(int, char, char *);

fun6type *getPtrFun6(void);

fun6type *getPtrFun6(void)
{
  return fun6;
}

Hard to read way:

int (*getPtrFun6_1(void))(int, char, char *);

int (*getPtrFun6_1(void))(int, char, char *)
{
    return fun6;
}

int foo(void)
{
    int (*f)(int, char, char *) = getPtrFun6_1();

    return f(1, 'a', "Test");
}

Test it yourself https://godbolt.org/z/erh63jTc8

If I comment on everything about fun6 in the source code, compile it and run it (just call fun5) I get the error "Segmentation fault".

Function pointer has to reference a valid function before it is dereferenced (called) as any other pointer. Your one is not initialized and it is not referencing a valid function.

BTW It is rather C code (not C++). In C++ use of function pointers (and generally pointers) should be avoided.

Comments

0

returnValue = (ptr_fun5)(15, 32); does not work because ptr_fun5 is initialized to a null pointer and is not given any other value until the statement ptr_fun5 = &fun5; inside fun5 is executed, which does not happen until fun5 is called.

One way to fix that is to delete int(*ptr_fun5)(int,int); and put int (*ptr_fun5)(int, int) = fun5; after the declaration of fun5. Then it will be initialized to the address of fun5.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.