delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2000/04/11/17:26:11

From: "Thomas Harte" <T DOT Harte AT btinternet DOT com DOT DELETE_HERE>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: stripping libraries
Date: Tue, 11 Apr 2000 19:04:10 +0100
Organization: BT Internet
Lines: 93
Message-ID: <8cvpkm$3e$1@plutonium.btinternet.com>
References: <0755aefe DOT 5d9e585f AT usw-ex0101-007 DOT remarq DOT com>
NNTP-Posting-Host: host213-1-149-84.btinternet.com
X-Newsreader: Microsoft Outlook Express 4.72.3155.0
X-MimeOLE: Produced By Microsoft MimeOLE V4.72.3155.0
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

>I have to create a library to distribute. This library needs to
>export only a few functions although internally it uses many.
>When I inspect the library file I find all internal function
>names etc. that I do not want to be visible. How can I strip all
>this?


This is the sort of thing that inspires people to move to C++. If you don't
want to do that fully, and depending how the linking of C to C++ works in
DJGPP (is this behaviour defined by ANSI?), the following may work.

Instead of having all your functions floating around free, create a class to
store them in. A class is a struct that can hold functions as well as data,
and can decide which of its members are visible to the outside world. For
example, you may have the following four procedures :

void draw_box(int x1, int y1, int x2, int y2);
void draw_title(int x1, int y, int x2, char *text);
void draw_button(int x1, int y1, int x2, int y2, char *text);
void draw_dialogue(struct DIALOGUE *menu);

Where the last one is meant to be used by a programmer, and the other three
are meant to be used only by draw_dialogue.

To create a class holding these functions is as easy as :

class dialogue
{
void draw_box(int x1, int y1, int x2, int y2);
void draw_title(int x1, int y, int x2, char *text);
void draw_button(int x1, int y1, int x2, int y2, char *text);
void draw_dialogue(struct DIALOGUE *menu);
};

And now, after declaring an object of that class type, you can access the
functions with :

object_name.draw_box(....)

and so on. But if you use the 'private' and 'public' tags in your class
dialogue, then only those entries within the 'public' section will be
visible to the rest of the program. E.g. :

class dialogue
{
private:
void draw_box(int x1, int y1, int x2, int y2);
void draw_title(int x1, int y, int x2, char *text);
void draw_button(int x1, int y1, int x2, int y2, char *text);
public:
void draw_dialogue(struct DIALOGUE *menu);
};

Means that the code

object_name.draw_box(...);

will now fail to compile - the function name draw_box is effectively not in
scope. But draw_dialogue can call those procedures, as it is a member of the
class. Be aware that when actually coding the functions you should declare
them like this :

void dialogue::draw_box(...)
{
<code here>
}

As :: resolves scope in C++.

Anyway, having done that, compiled the object files and ar'd them into a
library, you could put the object definition into a header file, and add
something like this to the bottom :

#ifndef __my_dialogue_object
class dialogue __my_dialogue_object;
#define draw_dialogue(x) __my_dialogue_object.draw_dialogue(x)
#endif

The upshoot being that draw_dialogue(...) is still defined and in scope for
your C code, without you having to declare an object or do any C++, and if
anyone does want to use the other functions having read the header file,
they can't from your library because they are declared private.

Actually, I'm not sure if its entirely correct to redeclare
'__my_dialogue_object' in every C file, but that sort of thing always worked
for me in C. It might be smarter to actually declare it in one C file only,
and refer to it as 'extern' in the #ifndef block.

Anyway, I hope I've given the basic idea behind one possible solution.

-Thomas


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019