D - Separating implementation from definition
- Derek Parnell (43/43) Mar 18 2004 I've struggled with this for a few hours now, and admit defeat.
-
John Reimer
(13/24)
Mar 18 2004
- Walter (4/47) Mar 18 2004 Check out the example in phobos for gc.d. There are two; one is the
- Derjo Phar (73/131) Mar 19 2004 There are two whats? Two files called 'gc.d'? Two examples? If so what a...
- =?ISO-8859-1?Q?Sigbj=F8rn_Lund_Olsen?= (5/18) Mar 19 2004 The garbage collector source is in /dmd/src/phobos/internal/gc
- John Reimer (11/11) Mar 19 2004 I understand what you are saying, and I apologize for my rather quick,
- John Reimer (11/11) Mar 19 2004 These topics have been discussed before. And Walter has gone into more
- J Anderson (5/6) Mar 19 2004 dig being a keyword here. Dig separates the implementation from
- John Reimer (4/11) Mar 20 2004 Yes, a reference to dig :-). The Dig toolkit is probably the best examp...
- John Reimer (71/71) Mar 19 2004 I hope this is what you were looking for:
- Derjo Phar (12/13) Mar 19 2004 Thank you John. Yes this is exactly it. I was almost there too. The only
- John Reimer (10/26) Mar 20 2004 In fact, you don't need the module statement. I believe that if you
- Derjo Phar (42/64) Mar 20 2004 doing
- John Reimer (9/17) Mar 20 2004 You know what? I never thought of using module keyword that way; the si...
- J C Calvarese (7/14) Mar 21 2004 In fact, there's already a tool available that does some of this. Dig's
-
John Reimer
(7/18)
Mar 22 2004
- larry cowan (16/87) Mar 20 2004 With the following changes in the implementation file, what has to be in...
- C. Sauls (4/4) Mar 20 2004 As I understand it, you simply provide a decleration/prototype for all
-
John Reimer
(11/14)
Mar 20 2004
I've struggled with this for a few hours now, and admit defeat. I'd like to be able to have a file that defines a class's public interface AND the class name, but not contain the implementation code. I'd like to do this so I can distribute the class definition and an .OBJ file, but without distributing the implementation code. I thought I could define an interface to do this but that isn't quite right either, as all that does is specify a set of member functions, and has nothing to do with a class Name etc. Here is what I'd like to do ... In a file called 'foo_defn.d' I'd have ... // The publicly exposed API for the Foo class. class Foo definition { this(); this(int pValue); ~this(); int TheValue(); void TheValue(int pValue); } And in another file 'foo.d' I'd have ... import foo_defn; class Foo implementation { int v_TheValue; this() {v_TheValue = 1;} ...etc... } I would then compile 'foo.d' to create 'foo.obj'. Then I would distribute 'foo.obj' and 'foo_defn.d' so that somebody else could create a file such as 'myfoo.d' ... import foo_defn; class MyFoo { Foo f; this() { f = new Foo;} ...etc... } They would then compile 'myfoo.d' and link in 'foo'obj'. This way, they could use my foo class without knowing how it was implemented. This all seems so basic to me that I'm sure I've missed something dead obvious. -- Derek
Mar 18 2004
Derek Parnell wrote:I've struggled with this for a few hours now, and admit defeat. I'd like to be able to have a file that defines a class's public interface AND the class name, but not contain the implementation code. I'd like to do this so I can distribute the class definition and an .OBJ file, but without distributing the implementation code. I thought I could define an interface to do this but that isn't quite right either, as all that does is specify a set of member functions, and has nothing to do with a class Name etc.<sip> I fail to see why a separate public interface is needed. The way I understood it was that D simpifies the work with its import. You just provide your object file and appropriate documentation so that your user knows how to access the public class details. Documentation amounts to the same thing as a the separate class interface anyway. You have fewer source files to worry about as well, meaning less chance of creating inconsistancies between the interface and the implementation (although you could still make mistakes in the documentation too ;-D ). Or maybe I'm not seeing things straight... Take care, John
Mar 18 2004
Check out the example in phobos for gc.d. There are two; one is the interface, the other is the definition. "Derek Parnell" <Derek.Parnell psyc.ward> wrote in message news:opr43anbhtu2m3b2 news.digitalmars.com...I've struggled with this for a few hours now, and admit defeat. I'd like to be able to have a file that defines a class's public interface AND the class name, but not contain the implementation code. I'd like to do this so I can distribute the class definition and an .OBJ file, but without distributing the implementation code. I thought I could define an interface to do this but that isn't quite right either, as all that does is specify a set of member functions, and has nothing to do with a class Name etc. Here is what I'd like to do ... In a file called 'foo_defn.d' I'd have ... // The publicly exposed API for the Foo class. class Foo definition { this(); this(int pValue); ~this(); int TheValue(); void TheValue(int pValue); } And in another file 'foo.d' I'd have ... import foo_defn; class Foo implementation { int v_TheValue; this() {v_TheValue = 1;} ...etc... } I would then compile 'foo.d' to create 'foo.obj'. Then I would distribute 'foo.obj' and 'foo_defn.d' so that somebody else could create a file such as 'myfoo.d' ... import foo_defn; class MyFoo { Foo f; this() { f = new Foo;} ...etc... } They would then compile 'myfoo.d' and link in 'foo'obj'. This way, they could use my foo class without knowing how it was implemented. This all seems so basic to me that I'm sure I've missed something dead obvious. -- Derek
Mar 18 2004
"Walter" <walter digitalmars.com> wrote in message news:c3e7hl$l03$2 digitaldaemon.com...Check out the example in phobos for gc.d. There are two; one is the interface, the other is the definition.There are two whats? Two files called 'gc.d'? Two examples? If so what are their file names? I really do not know what you are talking about. I found a file called gc.d in the folder 'phobus\std', all that contains is a collection of function templates - nothing to do with classes in there though. And I found a file called 'gcstats.d' in the folder 'phobus', but that just contains a structure definition - again no classes. Maybe I'm not explaining myself clearly enough. Sorry about that. I'll have another go... I want to enable a third party to use a CLASS that I have created, but I do not want to give that person the source code to my class's implementation. As I see it, to do that the person will need to have the OBJ file that I would supply. However, if that person is to refer to my class in their own source code, the D compiler needs to have a source definition of my class too. So the question is simply this -- How can I write a source code file that exposes the public API for my class, without exposing the implemention code? At first, I thought that the D interface concept would be just the thing. So I tried this... I created a file called 'Foo_i.d" that contained... interface i_Foo { int FuncA(); int FuncB(); ...etc... } Hoping that all the third party need to do then was to use this file thus ... import Foo_i; class SuperFoo: i_Foo { . . . } But all this meant was that now they had to implement FuncA, FuncB, etc... Not what I wanted! Next I created the file 'foo_i.d' that contained my complete class definition AND implementation code. I compiled that to get a OBJ file 'foo_i.obj'. I renamed that to 'foo.obj'. Then I create a file 'foo.d' that only had the parts of my Foo class that I wished to expose - some functions (not all) and none of the class's variables. Then I pretended to be the third party wishing to use the Foo class. So I create a file 'sfoo.d' that looked like this ... import foo; class SuperFoo: Foo { int FuncC(){return 1;} } This compiled okay, picking up my cut-down version of Foo's definition (from importing 'foo'). I then created 'test.d' with this ... import sfoo; void main() { SuperFoo a; a = new SuperFoo; a.FuncA(); a.FuncC(); } This also compiled okay. But it wouldn't link correctly. The functions that I exposed in my foo.d and the class Foo itself were all undefined. So then I changed 'sfoo.d' so it would import 'foo_i' rather than 'foo' then recompiled 'test.d' and it compiled and linked okay. NOt surprising as 'foo_i.d' contains my implementation code as well as the class API definition. So this is my problem. I don't want to distribute foo_i.d, the one with my class implementation code. Just documenting the Foo API is not enough. Sure it needs to be done, but that doesn't avoid the need for the third party to have the source code for the Foo class (including implementation code). I hope what I want to do is a bit clearer now. -- Derek"Derek Parnell" <Derek.Parnell psyc.ward> wrote in message news:opr43anbhtu2m3b2 news.digitalmars.com...interfaceI've struggled with this for a few hours now, and admit defeat. I'd like to be able to have a file that defines a class's publicdistributeAND the class name, but not contain the implementation code. I'd like to do this so I can distribute the class definition and an .OBJ file, but without distributing the implementation code. I thought I could define an interface to do this but that isn't quite right either, as all that does is specify a set of member functions, and has nothing to do with a class Name etc. Here is what I'd like to do ... In a file called 'foo_defn.d' I'd have ... // The publicly exposed API for the Foo class. class Foo definition { this(); this(int pValue); ~this(); int TheValue(); void TheValue(int pValue); } And in another file 'foo.d' I'd have ... import foo_defn; class Foo implementation { int v_TheValue; this() {v_TheValue = 1;} ...etc... } I would then compile 'foo.d' to create 'foo.obj'. Then I wouldsuch'foo.obj' and 'foo_defn.d' so that somebody else could create a fileas 'myfoo.d' ... import foo_defn; class MyFoo { Foo f; this() { f = new Foo;} ...etc... } They would then compile 'myfoo.d' and link in 'foo'obj'. This way, they could use my foo class without knowing how it was implemented. This all seems so basic to me that I'm sure I've missed something dead obvious. -- Derek
Mar 19 2004
Derjo Phar wrote:"Walter" <walter digitalmars.com> wrote in message news:c3e7hl$l03$2 digitaldaemon.com...The garbage collector source is in /dmd/src/phobos/internal/gc 'std' is just one of three directories in the phobos directory. Cheers, Sigbjørn Lund OlsenCheck out the example in phobos for gc.d. There are two; one is the interface, the other is the definition.There are two whats? Two files called 'gc.d'? Two examples? If so what are their file names? I really do not know what you are talking about. I found a file called gc.d in the folder 'phobus\std', all that contains is a collection of function templates - nothing to do with classes in there though. And I found a file called 'gcstats.d' in the folder 'phobus', but that just contains a structure definition - again no classes.
Mar 19 2004
I understand what you are saying, and I apologize for my rather quick, non-thinking reply. You are right. It can't be done the way I said. I think this has been discussed before, and I agree it's an important issue. The DMD compiler seems to be more suited for open source projects currently. But it does link to external C object files with the extern attribute and export directive, so I would think that there is a way to interface with external D object files as well. I've just never had to worry or deal with that particular problem. Have you tried searching this newsgroup for past posts on this topic? Later, John
Mar 19 2004
These topics have been discussed before. And Walter has gone into more detail in previous threads. A method of doing something like this is shown in the gc. You just have to dig far enough. This actually would be a very good topic for a tutorial, though. This thread in particular is pertanent and detailed: "Implementing extern methods" http://www.digitalmars.com/drn-bin/wwwnews?D/19210 Also, it's always a good idea to check for information on http://www.prowiki.org/wiki4d/wiki.cgi?FrontPage Hope that helps, John
Mar 19 2004
John Reimer wrote:You just have to dig far enough.dig being a keyword here. Dig separates the implementation from definition using doxygen and by compiling to a lib. -- -Anderson: http://badmama.com.au/~anderson/
Mar 19 2004
J Anderson wrote:John Reimer wrote:Yes, a reference to dig :-). The Dig toolkit is probably the best example of this kind of thing in action. Yet a highly simplified example helped me get a feel for how it worked.You just have to dig far enough.dig being a keyword here. Dig separates the implementation from definition using doxygen and by compiling to a lib.
Mar 20 2004
I hope this is what you were looking for: Here’s a quick tutorial for setting up an interface file and and implementation file. (I apologize about formatting... might turn up very bad in the newsgroup). STEP 1: Create your implementation file: /* -------------------------------------- */ module foo; import std.c.stdio; class Foo { public: int funcA() { printf(“Inside method implementation funcA of class Foo”); return 1; } int funcB() { printf(“Inside method implementation funcB of class Foo”); return 2; } } /* ----- end of implementation file ----- */ STEP 2: Compile the implementation file in a separate directory (your work directory for the project): dmd -c foo.d This should produce foo.obj. Move to another directory of your choice. This will be a directory that contains a project that will make use of the foo implementation. You will be providing an “interface” module that will allow the user to only see the public members of the class. So in this directory there will be: /* -------------------------------------- */ /* This module must be of the SAME NAME as the implementation module because of the way symbols are combined with the module name. */ module foo; class Foo { public: int funcA(); int funcB(); } /* ---------- end of interface module -------- */ The interface module is the file you will provide along with the foo.obj (implementation) to the developer. You do not compile this foo.d. It will be imported into the external developers project. An example: /* --- main project --- */ module project; import foo; int main( char[][] args ) { int a, b; Foo Foo1 = new Foo; printf("\nStarting from main():\n"); a=Foo1.funcA(); b=Foo1.funcB(); printf("\na = %d, b = %d\n", a, b); return 1; } The developer will then compile the project like so (making sure that the interface module and implementation object file are in the same directory; if they are not, remember to specify the correct paths): dmd project.d foo.obj -of project.exe The provided implementation is linked in with the project. The developer never sees the implementation details. Thanks to Walter for the for the gc reference ;-). Feel free to point any errors. I'm supposed to be busy studying for an exam... obviously I got sidetracked :-). Later, John
Mar 19 2004
"John Reimer" <jjreimer telus.net> wrote in message news:c3gnjg$1s5f$1 digitaldaemon.com...I hope this is what you were looking for:Thank you John. Yes this is exactly it. I was almost there too. The only difference between the correct way you have shown and the way I was doing it, was that in the correct way there is the line 'module foo;' at the start of both the definition file and the implementation file. When I was doing it, I did not have that line or any 'module' statement at all. I guess I didn't really understand the purpose of the module statement. It seems that this identifies the namespace for the file, and if not supplied, the namespace is the same as the file name. -- Derek
Mar 19 2004
Derjo Phar wrote:"John Reimer" <jjreimer telus.net> wrote in message news:c3gnjg$1s5f$1 digitaldaemon.com...In fact, you don't need the module statement. I believe that if you leave it out, the module name defaults to the filename. So you probably had it figured out on your own afterall. I just included it for clarity. For more information about the specifics of "module": http://www.digitalmars.com/d/module.html I also realize it may have been more accurrate to use the terms definition/implementation vereses interface/implementation. Oh well. Later, JohnI hope this is what you were looking for:Thank you John. Yes this is exactly it. I was almost there too. The only difference between the correct way you have shown and the way I was doing it, was that in the correct way there is the line 'module foo;' at the start of both the definition file and the implementation file. When I was doing it, I did not have that line or any 'module' statement at all. I guess I didn't really understand the purpose of the module statement. It seems that this identifies the namespace for the file, and if not supplied, the namespace is the same as the file name.
Mar 20 2004
"John Reimer" <jjreimer telus.net> wrote in message news:c3gvrr$2b48$1 digitaldaemon.com...Derjo Phar wrote:doing"John Reimer" <jjreimer telus.net> wrote in message news:c3gnjg$1s5f$1 digitaldaemon.com...I hope this is what you were looking for:Thank you John. Yes this is exactly it. I was almost there too. The only difference between the correct way you have shown and the way I wasstartit, was that in the correct way there is the line 'module foo;' at thedoingof both the definition file and the implementation file. When I wasItit, I did not have that line or any 'module' statement at all. I guess I didn't really understand the purpose of the module statement.supplied,seems that this identifies the namespace for the file, and if notI had read that section of the documentation many times before giving up. I now realize that the paragraph "Modules have a one-to-one correspondence with source files. The module name is the file name with the path and extension stripped off." was what confused me. Now I realize that the module name can actually be different from the file name. It's the module name that is the namespace name, and its this that is used by the linkeditor to resolve symbols in the .OBJ file. Anyhow, I now have two source files... //---------------- foo.d --------- module foo; import std.c.stdio; class Foo { private int x; /* expose */ int FuncA(){ printf("Inside method implementation funcA of class Foo\n"); return 1;} /* expose */ int FuncB(){ printf("Inside method implementation funcB of class Foo\n"); return 2;} } and ... //---------------- foo_i.d --------- module foo; class Foo { public: int FuncA(); int FuncB(); } So I compile foo.d to get a .OBJ file and I distribute this OBJ file with the foo_i.d file. The "/* expose */" is a tag I can use to generate the foo_i.d automatically via a preprocessor job. Thanks again. -- Derekthe namespace is the same as the file name.In fact, you don't need the module statement. I believe that if you leave it out, the module name defaults to the filename. So you probably had it figured out on your own afterall. I just included it for clarity. For more information about the specifics of "module": http://www.digitalmars.com/d/module.html
Mar 20 2004
<snip?So I compile foo.d to get a .OBJ file and I distribute this OBJ file with the foo_i.d file. The "/* expose */" is a tag I can use to generate the foo_i.d automatically via a preprocessor job. Thanks again.You know what? I never thought of using module keyword that way; the simple solution escaped me. That's a great idea because than the two files don't have to be the same name. And foo_i.d can point out the definition file better. Also the stripping of the implementation with a preprocessor or script is indeed the way to go. Good work, John
Mar 20 2004
John Reimer wrote:<snip> Also the stripping of the implementation with a preprocessor or script is indeed the way to go.In fact, there's already a tool available that does some of this. Dig's strip.d doesn't require the rest of Dig. It's not perfect, but it works on some cases that I've thrown at it.Good work, John-- Justin http://jcc_7.tripod.com/d/
Mar 21 2004
J C Calvarese wrote:John Reimer wrote:<snip lots of D code> Hmmm... I should have known. Thanks for posting it. That should make things easier :-). I was thinking a good 'ol python script was in order here. Later, John<snip> Also the stripping of the implementation with a preprocessor or script is indeed the way to go.In fact, there's already a tool available that does some of this. Dig's strip.d doesn't require the rest of Dig. It's not perfect, but it works on some cases that I've thrown at it.
Mar 22 2004
With the following changes in the implementation file, what has to be in the interface module (definition file?). In article <c3gnjg$1s5f$1 digitaldaemon.com>, John Reimer says...I hope this is what you were looking for: Here’s a quick tutorial for setting up an interface file and and implementation file. (I apologize about formatting... might turn up very bad in the newsgroup). STEP 1: Create your implementation file: /* -------------------------------------- */ module foo; import std.c.stdio; class Foo {static int basis = 0; int start = 0; static int funcS(int arg) { return start + arg; } int incrBase() { basis++; }public:this(int begin) { start = basis + begin; }int funcA() { printf(“Inside method implementation funcA of class Foo”);return ++start;} int funcB() { printf(“Inside method implementation funcB of class Foo”);return ++start;} } /* ----- end of implementation file ----- */ STEP 2: Compile the implementation file in a separate directory (your work directory for the project): dmd -c foo.d This should produce foo.obj. Move to another directory of your choice. This will be a directory that contains a project that will make use of the foo implementation. You will be providing an “interface” module that will allow the user to only see the public members of the class. So in this directory there will be: /* -------------------------------------- */ /* This module must be of the SAME NAME as the implementation module because of the way symbols are combined with the module name. */ module foo; class Foo { public: int funcA(); int funcB(); } /* ---------- end of interface module -------- */ The interface module is the file you will provide along with the foo.obj (implementation) to the developer. You do not compile this foo.d. It will be imported into the external developers project. An example: /* --- main project --- */ module project; import foo; int main( char[][] args ) { int a, b; Foo Foo1 = new Foo; printf("\nStarting from main():\n"); a=Foo1.funcA(); b=Foo1.funcB(); printf("\na = %d, b = %d\n", a, b); return 1; } The developer will then compile the project like so (making sure that the interface module and implementation object file are in the same directory; if they are not, remember to specify the correct paths): dmd project.d foo.obj -of project.exe The provided implementation is linked in with the project. The developer never sees the implementation details. Thanks to Walter for the for the gc reference ;-). Feel free to point any errors. I'm supposed to be busy studying for an exam... obviously I got sidetracked :-). Later, John
Mar 20 2004
As I understand it, you simply provide a decleration/prototype for all public members, and that's that... could be wrong, haven't tried it. -C. Sauls -Invironz
Mar 20 2004
larry cowan wrote:With the following changes in the implementation file, what has to be in the interface module (definition file?).<snip> Yes, a more thorough example would have been better, one that included private and static members. I may work out something later. Truth be told, I haven't experimented beyond this point, but my assumption was that of C. Sauls. You just reveal what you want to reveal in the definition (the public members). It should all work properly because it doesn't change how the implementation module operates internally. It shouldn't be too much work to add those additions and give it a try. Later, John
Mar 20 2004