Creating a REXX function library from scratch with Microsoft Visual C++ 6.0 is fairly easy. Let's create one such example which we'll call "mylib.dll".

  1. Go to the File menu and select New.

    Create a new project

  2. This opens up a dialog as shown below, allowing you to choose a type of project. Choose Win32 Dynamic Link Library.

    Choose project type
  3. Enter a name for your dll (minus the .DLL extension). We're going to create a DLL named "mylib.dll" so we enter "mylib" for the project name as shown below:

    Choose options

  4. Click on the Ok button.

  5. Another dialog opens as shown below, allowing you to choose some options.

    Choose options

    In answer to the question, "What kind of DLL would you like to create?", choose An empty DLL project if you're writing your DLL in ordinary C. If you're writing it in C++, you'll need to create A simple DLL project so that Visual C++ creates some extra files to accomodate C++. Just be aware that your REXX-callable functions can't be members of some class. They would need to be declared static.

    We're creating an external library in ordinary C, so we choose the first option.

  6. Click on the Finish button. This will create your project.
  7. Now it's time to create your source code containing your REXX-callable functions. Click on the New Text File button to open up an editor window into which you'll type your C source code.

    Create your C source file
  8. This opens an editor window called "Text1". Let's write a REXX-callable function named "TestFunction" which returns the REXX string "Hello World". Type the following in the "Text1" window. (You can cut and paste it from here).
    #include <windows.h>
    #include <rexxsaa.h> /* Assumes "rexxsaa.h" copied to your compiler's include directory */
    
    APIRET APIENTRY TestFunction(CONST CHAR *name, ULONG numargs, RXSTRING args[], CONST UCHAR *queuename, RXSTRING *retstr)
    {
       /* Copy "Hello World" to the return buffer */
       strcpy(retstr->strptr, "Hello World");
    
       /* Set the length */
       retstr->strlength = strlen(retstr->strptr);
    
       /* Tell the interpreter everything went ok */
       return(RXFUNC_OK);
    }

  9. Click on the Save button to save your C code to disk.

    Save your C source file
  10. This brings up a file dialog as shown below. Let's name our source code "mylib.c".

    Name your C source file
  11. Now let's officially add this source code to our project. Go to the Project menu and select Add to Project -> Files.

    Add your C source file
  12. This brings up a file dialog as shown below. You should see our source code named "mylib.c" listed. Double-click upon it. This adds the source code to our project.

    Pick out your C source file
  13. Now we need to create a definition file. This is simply a text file that lists the names of all of our REXX-callable functions so that the REXX script will be able to find them in our DLL. Click on the New Text File button to open up an editor window into which you'll type the information for the definition file.

    Create your definition file
  14. This opens another editor window called "Text2". Let's enter the information we need in the definition file. Our needs are simple. All we need to specify is the name of our DLL (ie, "mylib" after the LIBRARY keyword, and list the names of all of our REXX-callable functions (ie, "TestFunction") after the EXPORTS keyword. So, type the following in the "Text2" window. (You can cut and paste it from here).
    LIBRARY mylib
    EXPORTS
       TestFunction
    

  15. Click on the Save button to save your definition file to disk.

    Save your definition file
  16. This brings up a file dialog. Let's name our definition file "mylib.def" and save it to disk.

    Name your definition file
  17. Now let's officially add this definition file to our project. Go to the Project menu and select Add to Project -> Files.

    Add your definition file
  18. This brings up a file dialog as shown below. You won't see our definition file listed until you go down to "File of type" and select "Definition Files (.def)".

    List your definition file
  19. Now, you should see our definition file named "mylib.def" listed. Double-click upon it. This adds the definition file to our project.

    Pick out your definition file
  20. Now, we can create our actual function library by going to the Build menu and selecting Build mylib.dll.

    Build your DLL

If you followed the above with no mistakes, you should have created "mylib.dll". You built a debug version. (When you build your final version for release, make sure that you set the project to build the release version). So, your DLL should be in some "Debug" folder.

Now to test our DLL, let's create a REXX script that does an RXFUNCADD() on "TestFunction" and then calls TestFunction() and prints the return REXX string to the screen. You need to know the full path to your DLL. For example, maybe it's in a folder called "C:\MyCode\MyLib\Debug". (Alternately, you could copy your DLL to some system folder, but I think that it's too easy to forget to continually update it as you make changes to your code, and then you can accidentally end up testing the wrong version).

So, here's our test REXX script:

IF RXFUNCADD('TESTFUNCTION', 'C:\MyCode\MyLib\Debug\mylib', 'TestFunction') \= 0 THEN DO
   SAY "Can't load TestFunction in mylib" /* For Reginald, you can do SAY RXFUNCERRMSG() */
   RETURN
END
SAY TestFunction()
RETURN
If you intend to call functions in the interpreter such as RexxVariablePool(), then you should either follow the techniques outlined in Supporting various interpreters, or if you wish to support only Reginald, then do the following:

  1. Go to the Project menu and select Add to Project -> Files.

    Add Reginald's LIB file
  2. This brings up a file dialog. Look for the file named REGINALD.LIB that was supplied with Reginald's Developer's Kit. Double-click upon it. This adds the LIB to our project.