compileIt for revolution?

Alex Tweedly alex at
Wed Jun 22 19:15:09 EDT 2005

Derek Bump wrote:

> If one who knows C and could figure out some sort of Transcript 
> wrapper, then it would be possible.  There are many freeware and 
> public domain compilers out there, but finding one that successfully 
> compiles DLLs for Revolution is seemingly difficult.  I've been trying 
> for a few months now, but with my limited knowledge of C I end up 
> running into errors.
> I am working on this project, but the *confusing* Externals SDK 
> doesn't help.  It's pretty bad when I've used about 10 different 
> compilers (including MS Visual C) and I still can't get the samples to 
> compile properly.  But that's a whole different issue.

I had a lot of trouble getting it to work first time.
A week later, I had even more trouble getting it to work the second 
time.  (A sure sign that I hadn't really understood what I'd been doing 
first time .... not even well enough for my detailed notes to make it 

Third time was better ......  it only took me 4 tries and 2 false starts 
tonight :-)

Now I can almost do it reliably.

The thing I kept getting wrong was understanding when the binding 
happens, and what that implies.
The FAQ (in the "Externals" stack that came in the SDK says

> In order to bind to external libraries the "set externals to" function 
> must be used. This tells the engine the library or multiple libraries 
> that the engine should bind to the next time it starts up. Multiple 
> libraries should be on separate lines.

What I now do (having got it wrong often enough, including right now 
when I was writing down the step-by-step) is to start the stack up, set 
the externals, save it, quit Rev. Restart Rev, open the stack, run the 
script that sets externals again - then check that put the external of 
this stack and put the externalFunctions of this stack give me what I 
expect ....

SO you might want to retry your earlier efforts, taking extra care about 
that step.

If it's not that .... read on.

Here's a step-by-step that now works reliably for me  (even if I don't 
properly  understand one crucial step :-)

I use Bloodshed Dev C++ on Windows XP. I have  version
(it's GPL - but that doesn't impose GPL restrictions on code compiled 
with it).

0. Create a directory - keep things simple by making this a top-level 
directory with no spaces in the name.
(That's probably unnecessary, but I had trouble with spaces in file 
names. I think that was with one of the other compilers I tried earlier 
- but I haven't gone back to change this and see if everything still 
works ....)

00. unpack or unzip the Rev externals SDK into that directory.

1. make files this.c, this.h, this.def (see the end of the email for 
their contents)
(why this.def ?  and how did I figure out what goes into it ?  far less 
what to do with it ???
no idea, but it works now .....)

2. open Dev-c++

3. File / New / Project
Select       DLL    from the set of icons
Name the project "this"
Select C Project from the radio buttons
Click OK

In the file save dialog, make sure you select the directory where you 
are doing this work (not the default), with the name as "this" (should 
be default).

4. click on th "+" beside the Project in the left pane of the window

 It should expand to show two files - dllmain.c and dllmain.h

5. For each of these, in turn, right click on it, select "Remove File" 
(and say "no" to saving it).

6. Right click on the Project, select "Add to Project" and in the file 
dialog select  this.c

7. Repeat 6, selecting   XCmdGlue.c

8. Menu select   Project  /   Project Options    .... select the Tab for 
Go to the 3rd column (Linker) and add to the end of the existing line " 
--def this.def" (without the quotes)

The line should now read
--no-export-all-symbols --add-stdcall-alias --def this.def
and click "OK"

9. Menu select Execute  / Compile

You'll see a dialog that shows "compiling this.c", then "compiling 
XCmdGlue.c", then "Linking this.dll"
Check the log (select the "Log" tab to see it). If it all looks OK, 
check that you now have a this.dll file

10. Start Rev, create a new main stack, add one button and one field.
Make the button script be

> on mouseUp
>   put the effective filename of this stack into mVar
>   set the itemDel to "/"
>   put "this.dll" into item -1 of mVar
>   set the externals of this stack to mVar
>   put xname() into field "Field"
> end mouseUp

save it, and then click the button.
I think this will fail first time - you need to close the stack and 
re-open it for the binding to take effect.
See above - I actually save it, exit Rev, etc.    Probably unnecessary, 
but I had so much trouble from 'accidental success' the first time I 
tried all this, and couldn't repeat it second time, that I am just 
paranoid .....

With any luck, you now have a working stack+external.

So now when you try what you want to do, and it doesn't work, you have a 
base-line that you can compare against.

If you don't have luck, email me off-list and I'll send you all the 
files involved from my system, and you can re-create the steps seeing 
what differs. I did this, comparing file sizes of  the binaries, at one 
point, to discover that I was including the wrong .def file).


> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> #include "XCmdGlue.h"
> #include "this.h"
> /*
>  * This global table has one entry per XCMD/XFCN.
>  * The first entry is the name of the handler
>  * The second entry is the type (XCOMMAND or XFUNCTION)
>  * The third entry is a space for the atom (used by the engine)
>  * The fourth entry is the name of the 'C' function to call
>  * The fifth entry is a callback called if the user aborts
>  * Note that the last entry in the table is a NULL entry
>  * which is used to measure the size of the table.
>  */
> Xternal Xtable[] = {
>     {"xname", XFUNCTION, 0, XGetName, XCabort},
>     {"", XNONE, 0, NULL, NULL}
> };
> /*
>  * This string identifies this external to the engine
>  */
> char Xname[] = "runrev externals";
> void XCabort()
> {
>   fprintf(stderr, "external abort");
> }
> void XGetName(char *args[], int nargs, char **retstring, Bool *pass, 
> Bool *error)
> {
>     *pass = False;    // don't pass the command up the chain
>     *error = False;    // call was successful
>     *retstring = istrdup ("this is my name");
> }


> #ifdef __STDC__
> extern void XGetName(char *args[], int nargs, char **retstring, Bool 
> *pass, Bool *error);
> #else
> extern void XGetName();
> #endif
> extern void XCabort();
> extern Xternal Xtable[];
> extern char Xname[];


> LIBRARY external
> EXPORTS getXtable
(I rather suspect that first line should be
I think this is an accidental artifact of the sample being called 
external.h - but have no clue how to tell. Changing it doesn't appear to 
have any effect).

Alex Tweedly

No virus found in this outgoing message.
Checked by AVG Anti-Virus.
Version: 7.0.323 / Virus Database: 267.7.8/22 - Release Date: 17/06/2005

More information about the use-livecode mailing list