0

I am trying one of the examples listened in the 'how do function pointers works in C' question, and I am stucking in a Undefined symbols for architecture x86_64 error.

The full log:

Undefined symbols for architecture x86_64:
"_getString", referenced from:
_newString in main-3adb06.o
"_lengthString", referenced from:
_newString in main-3adb06.o
"_setString", referenced from:
_newString in main-3adb06.o
ld: symbol(s) not found for architecture x86_64

The code I used:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct String_Struct* String;

struct String_Struct
{
char* (*get)(const void* self);
void (*set)(const void* self, char* value);
int (*length)(const void* self);
};

char* getString(const void* self);
void setString(const void* self, char* value);
int lengthString(const void* self);

String newString();

String newString()
{
String self = (String)malloc(sizeof(struct String_Struct));

self->get = &getString;
self->set = &setString;
self->length = &lengthString;

self->set(self, "");

return self;
}

int main(){
String s1 = newString();
s1->set(s1, "Hello, World!");
}

(the same as in the answer).

Teun
  • 3
  • 2
  • 3
    You really don't have getString... I suppose you forget to add/write those functions? – xosp7tom Dec 25 '16 at 15:14
  • can you provide a link to the 'how does function pointers works in C' question? (it might have been renamed/removed?) – pseyfert Dec 25 '16 at 15:22
  • http://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work – Teun Dec 25 '16 at 15:38
  • when linking, the actual functions (getString(), setString(), and lengthString()) need to exist. They do not exist in the posted code – user3629249 Dec 25 '16 at 18:34
  • it is a very bad idea to hide a * as part of a typedef statement, especially if the resulting type name does not include some indication that it is a pointer. – user3629249 Dec 25 '16 at 18:35
  • regarding this line: `String newString();` This is prototyping a function that can have any number of parameters (including no parameters). This causes the compiler to produce code to handle those possible parameters. Strongly suggest using: `String newString( void );` so the compiler produces the correct code – user3629249 Dec 25 '16 at 18:35
  • for ease of readability and understanding, please indent the code consistently. indent after every opening brace '{'. unindent before every closing brace '}'. Suggest using 4 spaces for each indent level as that is wide enough to be visible even with variable width fonts. – user3629249 Dec 25 '16 at 18:38

1 Answers1

0

This has nothing to do with the x86_64 architecture, the functions

char* getString(const void* self);
void setString(const void* self, char* value);
int lengthString(const void* self);

are declared but never defined.

The compilation will succeed because the compiler doesn't need to know where those functions actually are1, it only needs to know that they exists and their signature to perform the type checking. It is the job of the linker to find those functions in any object file being linked.
Since they are defined nowhere, the linking fails.


The answer you took this code from is just a showcase on how to implement OOP in C.
The code is not intended to be run, the implementation details, like the definition of the functions above, are left to the reader.
You should always read the full answer before copy-pasting the code and under no circumstances use code that you don't fully understand.
Furthermore, always take a look at the comments.

The answer is actually very inaccurate on how OOP is implemented, functions pointers are not used in implementing methods (unless they are virtual) as the typing is static and known at compile time (and so also are the methods to invoke, not need to use function pointers).

Functions pointers are no conceptually different from ordinary pointers or arrays, all these types let you access other variables based on the value of another variable (kind of meta-variables).
You can imagine that all functions have an unique (among the whole process) number associated with them and that a function pointer is just a variable that can hold such numbers.
When invoked, a function pointer will retrieve the function associated with the number it currently holds and execute it.
To be minimally type safe, function pointers, like ordinary pointers, carry a function signature.


1 In this case they have external linkage so the compiler won't even warn about the absence of a definition, as it expects it to be in another translation unit. Even if they had static linkage (i.e. internal-linkage in standardese) forward declaration is allowed, so the syntax is still valid (though GCC emits a warning).

Community
  • 1
  • 1
Margaret Bloom
  • 41,768
  • 5
  • 78
  • 124