Hiding implementation details when passing data around - c

I'm not even sure how to properly formulate question about this.
I'm writing a library where I have multiple implementations (multiple libraries out of one). I want to hide as much as possible, if not all, implementation details from client app, in order to write an app disregarding implementation details.
It's all fine when implementation is contained within one function. However, often I need to instantiate a struct from library, do something to it with a function from library, resume writing app as normal, and then return to a function from library with data from previous function from library.
Struct details are important ONLY to library functions. I don't need to see or touch those from client application apart from passing them around because of this.
So, is there a way to hide struct details from client app and still be able to use it or if there's another way of doing this by some form of encapsulation or maybe even some kind of data (globals?) visible only to library?
Here's my lame illustration example with code:
/*
library_private.h
*/
#if (A)
{
struct mystruct_t {
A *something;
}
}
#else
struct mystruct_t {
B *something;
}
#endif
/*
library_public.h
*/
struct mystruct_t;
/*
library.c
*/
struct mystruct_t* create() {
struct mystruct_t *handle = malloc(sizeof(struct mystruct_t));
return handle;
}
/*
client.h
*/
struct mystruct_t;
/* but, I need a definition, so I have to repeat either from library_private.h */
/*
client.c
*/
int main(int argc, char const *argv[]) {
struct mystruct_t *handle = create();
/*...*/
something(handle);
return 0;
}

Cast to a void * when returning and back to structure mystruct_t just after passing into a function. This is not great as you will loose some of the compiler type checking.

client.c (or client.h) should include library_public.h. There is no need to have the structure definition. Only its declaration struct mystruct_t; is enough to use pointers to the structure. Of course, you cannot access its members, but that is exactly what you want in this case.

Related

Using opaque pointers internally in library

When writing a library, you sometimes want to hide implementation details from the user. The ideal tool for this is opaque structs or opaque pointers.
A problem arises when another source file in the library wishes to use data from this struct. For example: this is the header file apple.h:
typedef struct apple_ Apple;
Apple* new_apple();
void delete_apple(Apple* a);
/* ... */
This is the definition of the struct Apple:
typedef struct apple_ {
int taste; /* the higher the better */
}
Typically, this part resides in apple.c.
But what if a Store wishes to rank their apples according to taste? This could be store.c:
#include "apple.h"
void rankApples(Store* store) {
int t = store->apples[0]->taste; /* unreachable field */
}
A solution could be to duplicate the struct definition (I don't want that) or to create a function in apple.[hc]: int taste_apple(Apple* a) { return a->taste; }, but I'd rather that users don't know how tasty apples are.
How can this be solved? Should I create another header file used by both apple.c and store.c? How do I stop users from including that header file?
When hiding library detail from consuming clients, it is not uncommon to do what you described in your last paragraph. But you don't need to "ship the details" with your lib and public header.
For example:
mylib.h
#ifndef MYLIB_H
typedef struct Data Data;
void Func(Data *data);
#endif
mylibint.h
#ifndef MYLIB_H_INTERNAL
#define MYLIB_H_INTERNAL
struct Data
{
// implementation goes here
int value;
};
#endif
mylib.c
#include "mylib.h"
#include "mylibint.h"
Data *GetData()
{
return calloc(1, sizeof(Data));
}
void FreeData(Data *data)
{
free(data);
}
void DoSomething(Data * data)
{
// do something with data
}
In doing so, your library will build, consuming both headers while doing so. The only header you need to ship with it is mylib.h. Later, a client can do this:
client.c
#include "mylib.h"
int main()
{
Data *data = GetData();
DoSomething(data);
FreeData(data);
}
And they are left blissfully unaware of what Data is besides some opaque type.
You want the store to know a piece of information, but you are not willing to give it to them. That just doesn't make sense.
You can either make apple structure public to both files (that might mean separating it and including it by both, but not giving it to the user), or as you said, create a function that would retrieve the taste of an apple.
However, I'd say that if the taste is going to be used for the ranking purposes only, why don't you just create a function, let's say getPoints a store could use to rank the apples?
int getPoints(Apple* a) {
return a->taste*2;
}

Library Handles in node-ffi

I'm playing with integrating the gssapi into node.js. Im not sure how to represent this:
The gss_init_sec_context function contains many struct based parameters, some of which are nested pretty deeply. For example this struct:
typedef struct gss_ctx_id_struct
{
gss_OID mech;
#ifdef USE_KERBEROS5
struct _gss_krb5_ctx_struct *krb5;
#endif
} gss_ctx_id_desc;
So based on this I'm guessing I need to implement some kind of Structure (with ref-struct) to represent the krb5 pointer (since kerberos5 is being used). So I looked at this _gss_krb_ctx_struct and saw this...
typedef struct _gss_krb5_ctx_struct {
Shishi *sh;
Shishi_ap *ap;
Shishi_tkt *tkt;
Shishi_key *key;
gss_name_t peerptr;
int acceptor;
uint32_t acceptseqnr;
uint32_t initseqnr;
OM_uint32 flags;
int reqdone;
int repdone;
} _gss_krb5_ctx_desc, *_gss_krb5_ctx_t;
Where Shishi is a pointer to a library, and shishi_ap appears to be a pointer to a function. I'm not sure how to implement these things in node-ffi. Can someone give me some guidance here?

Implementing callbacks between files in C

My program contains the following files: data_handler.c, app.c and callback_struct.h.
data_handler.c retrieves data from functions in app.c, by making callbacks to app.c.
The program should allow the user to define a set of functions with arbitrary names in app.c. The user does this by defining his functions, and associating them with a set of initiated function pointers (ptr_func1, ptr_func2 etc.), found in callback_struct.h.
With this approach I want to eliminate the need of making explicit calls from data_handler.c to the user functions in app.c (so that the code in data_handler.c do not have to be modified if the user changes his function names for example), neither do I want to have to include (#) app.c into data_handler.c.
Clearly there is something I'm not getting here. I would be grateful if someone could help me understand what I'm doing wrong, and perhaps give me some indications on whether or not I'm on the right track with my suggested implementation
See my implementation below:
callback_struct.h:
struct callback_struct{
int (*ptr_func1)(void);
int (*ptr_func2)(void);
// etc...
};
extern struct callback_struct user_functions; // should be defined in app.c
app.c
#include "callback_struct.h"
int user_function_func1(void);
int user_function_func2(void);
struct callback_struct user_functions={
.ptr_func1 = user_function_func1,
.ptr_func2 = user_function_func2,
};
int user_function_func1(void){
int data = 1; // for example...
return data;
}
int user_function_func2(void){
int data = 2; // for example...
return data;
}
// etc.....
data_handler.c
#include "callback_struct.h"
/*this function makes callbacks to app.c to retrieve data*/
void get_data(int (*ptr)(void)){
int retrieved_data=ptr();
}
void main(void){
get_data(user_functions.ptr_func1);
get_data(user_functions.ptr_func2);
// etc....
}
It's only a syntax error. Just replace
extern struct user_functions={
by
struct callback_struct user_functions={
in your app.c and it will work.
When you declare a global variable 'extern', you are telling the compiler that this variable is instantiated (and possibly initialized) somewhere else in the code.
Therefore, you should not declare it 'extern' and initialize it in the same line, which is exactly what you did in file app.c.

How do I mock objects without inheritance (in C)?

We use a simple object model for our low level networking code at work where struct pointers are passed around to functions which are pretending to be methods. I've inherited most of this code which was written by consultants with passable C/C++ experience at best and I've spent many late nights trying to refactor code into something that would resemble a reasonable structure.
Now I would like to bring the code under unit testing but considering the object model we have chosen I have no idea how to mock objects. See the example below:
Sample header (foo.h):
#ifndef FOO_H_
#define FOO_H_
typedef struct Foo_s* Foo;
Foo foo_create(TcpSocket tcp_socket);
void foo_destroy(Foo foo);
int foo_transmit_command(Foo foo, enum Command command);
#endif /* FOO_H_ */
Sample source (foo.c):
struct Foo_s {
TcpSocket tcp_socket;
};
Foo foo_create(TcpSocket tcp_socket)
{
Foo foo = NULL;
assert(tcp_socket != NULL);
foo = malloc(sizeof(struct Foo_s));
if (foo == NULL) {
goto fail;
}
memset(foo, 0UL, sizeof(struct Foo_s));
foo->tcp_socket = tcp_socket;
return foo;
fail:
foo_destroy(foo);
return NULL;
}
void foo_destroy(Foo foo)
{
if (foo != NULL) {
tcp_socket_destroy(foo->tcp_socket);
memset(foo, 0UL, sizeof(struct Foo_s));
free(foo);
}
}
int foo_transmit_command(Foo foo, enum Command command)
{
size_t len = 0;
struct FooCommandPacket foo_command_packet = {0};
assert(foo != NULL);
assert((Command_MIN <= command) && (command <= Command_MAX));
/* Serialize command into foo_command_packet struct */
...
len = tcp_socket_send(foo->tcp_socket, &foo_command_packet, sizeof(foo_command_packet));
if (len < sizeof(foo_command_packet)) {
return -1;
}
return 0;
}
In the example above I would like to mock the TcpSocket object so that I can bring "foo_transmit_command" under unit testing but I'm not sure how to go about this without inheritance. I don't really want to redesign the code to use vtables unless I really have to. Maybe there is a better approach to this than mocking?
My testing experience comes mainly from C++ and I'm a bit afraid that I might have painted myself into a corner here. I would highly appreciate any recommendations from more experienced testers.
Edit:
Like Richard Quirk pointed out it is really the call to "tcp_socket_send" that I want to override and I would prefer to do it without removing the real tcp_socket_send symbol from the library when linking the test since it is called by other tests in the same binary.
I'm starting to think that there is no obvious solution to this problem..
You can use macro to redefine tcp_socket_send to tcp_socket_send_moc and link with real tcp_socket_send and dummy implementation for tcp_socket_send_moc.
you will need to carefully select the proper place for :
#define tcp_socket_send tcp_socket_send_moc
Have a look at TestDept:
http://code.google.com/p/test-dept/
It is an open source project that aims at providing possiblity to have alternative implementations, e.g. stubs, of functions and being able to change in run-time which implementation of said function to use.
It is all accomplished by mangling object files which is very nicely described on the home page of the project.
Alternatively, you can use TestApe TestApe Unit testing for embedded software - It can do it, but note it is C only.
It would go like this -->
int mock_foo_transmit_command(Foo foo, enum Command command) {
VALIDATE(foo, a);
VALIDATE(command, b);
}
void test(void) {
EXPECT_VALIDATE(foo_transmit_command, mock_foo_transmit_command);
foo_transmit_command(a, b);
}
Not sure what you want to achieve.
You can add all foo_* functions as function pointer members to struct Foo_s but you still need to explicitly pass pointer to your object as there is no implicit this in C. But it will give you encapsulation and polymorphism.
What OS are you using? I believe you could do an override with LD_PRELOAD on GNU/Linux: This slide looks useful.
Use Macro to refine tcp_socket_send is good. But the mock only returns one behavior. Or you need implement some variable in the mock function and setup it differently before each test case.
Another way is to change tcp_socket_send to function point. And points it to different mock function for different test case.
To add to Ilya's answer. You can do this.
#define tcp_socket_send tcp_socket_send_moc
#include "your_source_code.c"
int tcp_socket_send_moc(...)
{ ... }
I use the technique of including the source file into the unit testing module to minimize modifications in the source file when creating unit tests.

How do I write a dispatcher, if my compiler's support for pointers-to-functions is broken?

I am working on an embedded application where the device is controlled through a command interface. I mocked the command dispatcher in VC and had it working to my satisfaction; but when I then moved the code over to the embedded environment, I found out that the compiler has a broken implementation of pointer-to-func's.
Here's how I originally implemented the code (in VC):
/* Relevant parts of header file */
typedef struct command {
const char *code;
void *set_dispatcher;
void *get_dispatcher;
const char *_description;
} command_t;
#define COMMAND_ENTRY(label,dispatcher,description) {(const char*)label, &set_##dispatcher, &get_##dispatcher, (const char*)description}
/* Dispatcher data structure in the C file */
const command_t commands[] = {
COMMAND_ENTRY("DH", Dhcp, "DHCP (0=off, 1=on)"),
COMMAND_ENTRY("IP", Ip, "IP Address (192.168.1.205)"),
COMMAND_ENTRY("SM", Subnet, "Subunet Mask (255.255.255.0)"),
COMMAND_ENTRY("DR", DefaultRoute, "Default router (192.168.1.1)"),
COMMAND_ENTRY("UN", Username, "Web username"),
COMMAND_ENTRY("PW", Password, "Web password"),
...
}
/* After matching the received command string to the command "label", the command is dispatched */
if (pc->isGetter)
return ((get_fn_t)(commands[i].get_dispatcher))(pc);
else
return ((set_fn_t)(commands[i].set_dispatcher))(pc);
}
Without the use of function pointers, it seems like my only hope is to use switch()/case statements to call functions. But I'd like to avoid having to manually maintain a large switch() statement.
What I was thinking of doing is moving all the COMMAND_ENTRY lines into a separate include file. Then wraps that include file with varying #define and #undefines. Something like:
/* Create enum's labels */
#define COMMAND_ENTRY(label,dispatcher,description) SET_##dispatcher, GET_##dispatcher
typedef enum command_labels = {
#include "entries.cinc"
DUMMY_ENUM_ENTRY} command_labels_t;
#undefine COMMAND_ENTRY
/* Create command mapping table */
#define COMMAND_ENTRY(label,dispatcher,description) {(const char*)label, SET_##dispatcher, GET_##dispatcher, (const char*)description}
const command_t commands[] = {
#include "entries.cinc"
NULL /* dummy */ };
#undefine COMMAND_ENTRY
/*...*/
int command_dispatcher(command_labels_t dispatcher_id) {
/* Create dispatcher switch statement */
#define COMMAND_ENTRY(label,dispatcher,description) case SET_##dispatcher: return set_##dispatcher(pc); case GET_##dispatcher: return get_##dispatcher(pc);
switch(dispatcher_id) {
#include "entries.cinc"
default:
return NOT_FOUND;
}
#undefine COMMAND_ENTRY
}
Does anyone see a better way to handle this situation? Sadly, 'get another compiler' is not a viable option. :(
--- Edit to add:
Just to clarify, the particular embedded environment is broken in that the compiler is supposed to create a "function-pointer table" which is then used by the compiler to resolve calls to functions through a pointer. Unfortunately, the compiler is broken and doesn't generate a correct function-table.
So I don't have an easy way to extract the func address to invoke it.
--- Edit #2:
Ah, yes, the use of void *(set|get)_dispatcher was my attempt to see if the problem was with the typedefine of the func pointers. Originally, I had
typedef int (*set_fn_t)(cmdContext_t *pCmdCtx);
typedef int (*get_fn_t)(cmdContext_t *pCmdCtx);
typedef struct command {
const char *code;
set_fn_t set_dispatcher;
get_fn_t get_dispatcher;
const char *_description;
} command_t;
You should try changing your struct command so the function pointers have the actual type:
typedef struct command {
const char *code;
set_fn_t set_dispatcher;
get_fn_t get_dispatcher;
const char *_description;
} command_t;
Unfortunately, function pointers are not guaranteed to be able to convert to/from void pointers (that applies only to pointers to objects).
What's the embedded environment?
Given the information posted in the updates to the question, I see that it's really a bugged compiler.
I think that your proposed solution seems pretty reasonable - it's probably similar to what I would have come up with.
A function pointer isn't actually required to fit in a void*. You could check to make sure that the value you're calling is actually the address of the function. If not, use a function pointer type in the struct: either get_fn_t, or IIRC void(*)(void) is guaranteed to be compatible with any function pointer type.
Edit: OK, assuming that calling by value can't be made to work, I can't think of a neater way to do what you need than auto-generating the switch statement. You could maybe use an off-the-shelf ASP-style preprocessor mode for ruby/python/perl/php/whatever prior to the C preprocessor. Something like this:
switch(dispatcher_id) {
<% for c in commands %>
case SET_<% c.dispatcher %>: return set_<% c.dispatcher %>(pc);
case GET_<% c.dispatcher %>: return get_<% c.dispatcher %>(pc);
<% end %>
default:
return NOT_FOUND;
}
might be a bit more readable than the macro/include trick, but introducing a new tool and setting up the makefiles is probably not worth it for such a small amount of code. And the line numbers in the debug info won't relate to the file you think of as the source file unless you do extra work in your preprocessor to specify them.
Can you get the vendor to fix the compiler?
To what extent is the pointer-to-function broken?
If the compiler allows you to get the address of a function (I'm from C++, but &getenv is what I mean), you could wrap the calling convention stuff into assembler.
As said, I'm a C++ssie, but something in the way of
; function call
push [arg1]
push [arg2]
call [command+8] ; at the 4th location, the setter is stored
ret
If even that is broken, you could define an array of extern void* pointers which you define, again, in assembly.
try this syntax:
return (*((get_fn_t)commands[i].get_dispatcher))(pc);
It's been awhile since I've done C & function pointers, but I believe the original C syntax required the * when dereferencing function pointers but most compilers would let you get away without it.
Do you have access to the link map?
If so, maybe you can hack your way around the wonky function-pointer table:
unsigned long addr_get_dhcp = 0x1111111;
unsigned long addr_set_dhcp = 0x2222222; //make these unique numbers.
/* Relevant parts of header file */
typedef struct command {
const char *code;
unsigned long set_dispatcher;
unsigned long get_dispatcher;
const char *_description;
} command_t;
#define COMMAND_ENTRY(label,dispatcher,description) {(const char*)label,
addr_set_##dispatcher, addr_get_##dispatcher, (const char*)description}
Now compile, grab the relevant addresses from the link map, replace the constants, and recompile. Nothing should move, so the map ought to stay the same. (Making the original constants unique should prevent the compiler from collapsing identical values into one storage location. You may need a long long, depending on the architecture)
If the concept works, you could probably add a post-link step running a script to do the replacement automagically. Of course, this is just a theory, it may fail miserably.
Maybe, you need to look into the structure again:
typedef struct command {
const char *code;
void *set_dispatcher; //IMO, it does not look like a function pointer...
void *get_dispatcher; //more like a pointer to void
const char *_description;
} command_t;
Let say your dispatchers have the following similar function definition:
//a function pointer type definition
typedef int (*genericDispatcher)(int data);
Assume that the dispatchers are like below:
int set_DhcpDispatcher(int data) { return data; }
int get_DhcpDispatcher(int data) { return 2*data; }
So, the revised structure will be:
typedef struct command {
const char *code;
genericDispatcher set_dispatcher;
genericDispatcher get_dispatcher;
const char *_description;
} command_t;
Your macro will be:
#define COMMAND_ENTRY(label,dispatcher,description) \
{ (const char*)label, \
set_##dispatcher##Dispatcher, \
get_##dispatcher##Dispatcher, \
(const char*)description }
Then, you can set your array as usual:
int main(int argc, char **argv)
{
int value1 = 0, value2 = 0;
const command_t commands[] = {
COMMAND_ENTRY("DH", Dhcp, "DHCP (0=off, 1=on)")
};
value1 = commands[0].set_dispatcher(1);
value2 = commands[0].get_dispatcher(2);
printf("value1 = %d, value2 = %d", value1, value2);
return 0;
}
Correct me, if I am wrong somewhere... ;)

Resources