home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / vos2-121.zip / v / contrib / vdll.how < prev    next >
Internet Message Format  |  1998-07-03  |  16KB

  1. From eyalb@aks.com  Mon Feb  3 08:23:09 1997
  2. Received: from dockmaster.aks.com by mimbres.cs.unm.edu (5.65/033093) with SMTP
  3.     id <AA07327@mimbres.cs.unm.edu>; Mon, 3 Feb 97 08:23:09 -0700
  4. Received: (from uucp@localhost) by dockmaster.aladdin.co.il (8.6.12/8.6.12) id RAA19870 for <wampler@cs.unm.edu>; Mon, 3 Feb 1997 17:27:08 -0500
  5. Received: from pink.aladdin.co.il(10.1.1.132) by dockmaster.aladdin.co.il via smap (V1.3)
  6.     id sma019864; Mon Feb  3 17:26:47 1997
  7. Received: from eyalb.aladdin.co.il (eyalb.aladdin.co.il [10.1.1.164]) by pink.aladdin.co.il (8.6.12/8.6.12) with SMTP id RAA31553 for <wampler@cs.unm.edu>; Mon, 3 Feb 1997 17:28:21 +0200
  8. Message-Id: <2.2.32.19970203192324.0067f7a4@mailhost>
  9. X-Sender: eyalb@mailhost
  10. X-Mailer: Windows Eudora Pro Version 2.2 (32)
  11. Mime-Version: 1.0
  12. Content-Type: text/plain; charset="us-ascii"
  13. Date: Mon, 03 Feb 1997 17:23:24 -0200
  14. To: wampler@cs.unm.edu
  15. From: Eyal Ben-David <eyalb@aks.com>
  16. Subject: V Win32 DLL -- HowTo
  17. Status: RO
  18.  
  19.  
  20. Recently I built the V (ver116) library as a Win32 DLL with:
  21.  
  22. Watcom  C++  10.6
  23. Visual  C++  4.2
  24. Borland C++  5.0
  25.  
  26. I believe that the method is also applicable to other compilers
  27. and previous versions of the above compilers. I tested the V apps
  28. that come with    V and they all run OK. The port is not complicated
  29. and it can be automated. I've already done it in the past (v115) but only
  30. for Watcom and with a lot of manual work.
  31.  
  32. Some Features:
  33. ~~~~~~~~~~~~~~
  34. - Same source files for building static and dynamic library.
  35. - Same source files for all compilers.
  36. - Application code is not changed at all !
  37. - All V sample programs and tests run OK.
  38. - Automatic build from sources to dll.
  39. - V implementation is not changed at all.
  40.  
  41. I think that future releases of V should be DLL-aware, so this is
  42. a first step towards this goal.
  43.  
  44. I want to upload my work and need some help about it. Meanwhile, here
  45. are the changes needed to build the DLL.
  46.  
  47.  
  48. 1. Global Changes in header files
  49. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  50. Dll's have interface similar to C++ `public' and `private'. When
  51. you use a dll you usually communicate with its `public' functions.
  52. You achieve publicity by changing the attribute of a function.
  53. for example:
  54.     void __declspec(dllexport) foo(int a);
  55.  
  56. When you want to export a whole class (along with its static data)
  57. you declare:
  58.  
  59.     class __declspec(dllexport) ClassName {
  60.     // ...
  61.     };
  62.  
  63. Since I use a single source code for both dynamic library 
  64. and static library, I used some macros in the file "v/v_defs.h":
  65.  
  66. ************************************************
  67. // support for V DLL
  68. #if defined (__BORLANDC__)
  69.   #define V_EXPORT  __export
  70.   #define V_IMPORT  __import
  71. #else
  72.   #define V_EXPORT  __declspec(dllexport)
  73.   #define V_IMPORT  __declspec(dllimport)
  74. #endif    
  75.  
  76. #if defined (BUILD_V_DLL)
  77.   #if !defined(_WIN32)
  78.     #error V DLL is supported under Win32 only.
  79.   #endif
  80.   #define V_CLASS V_EXPORT
  81.   #define V_FUNC  V_EXPORT
  82. #else
  83.   #define V_CLASS  
  84.   #define V_FUNC
  85. #endif  
  86.  
  87.  
  88. //  See Appendix for explanation
  89. //
  90. #define DUMMY_DEF_CTOR(ClassName)
  91.  
  92. //  The following is needed only when using VC++.
  93. //
  94. #if defined (BUILD_V_DLL) && defined (_MSC_VER)
  95.   #undef  DUMMY_DEF_CTOR
  96.   #define DUMMY_DEF_CTOR(ClassName)  \
  97.     friend void _dummy();            \
  98.     protected: ClassName() {}        \
  99.     private:
  100. #endif
  101. *********************************************************
  102.  
  103.  
  104. So, the first thing to do is:
  105.  
  106.   1.1  Add the code fragment (from above) to the beginning of "v_defs.h"
  107.   1.2  Add V_CLASS attribute in every class declaration.
  108.   1.3  Add DUMMY_DEF_CTOR for in every V class that does
  109.        not have a default constructor (or a constructor with all
  110.        default arguments)
  111.        for example:
  112.  
  113.        class V_CLASS ClassName {
  114.            DUMMY_DEF_CTOR(ClassName)  // first thing !
  115.  
  116.            // ...
  117.        };
  118.  
  119.        This is related only to Visual C++  -- See Appendix.
  120.  
  121.   1.4  Add V_FUNC attribute for every global function.
  122.       
  123.       V_DEFS.H
  124.       ~~~~~~~~
  125.       extern void V_FUNC vSysWarning(char* msg);
  126.       extern void V_FUNC vSysError(char* msg);
  127.  
  128.       VUTIL.H:
  129.       ~~~~~~~~
  130.       extern void V_FUNC LongToStr(long intg, char* str);
  131.       extern void V_FUNC IntToStr(int intg, char* str);
  132.       extern int  V_FUNC vLblLen(char *str);
  133.       extern int  V_FUNC vTextLen(char *str, int& numLines);
  134.       extern void V_FUNC vGetLocalTime(char* tm);
  135.       extern void V_FUNC vGetLocalDate(char* tm);
  136.       extern void V_FUNC ByteToStr(unsigned char byteval, char* str);
  137.       extern long V_FUNC StrToLong(char* str);
  138.  
  139.       VAPP.H  (inside vApp class declaration)
  140.       ~~~~~~
  141.       friend int V_FUNC CMain(HANDLE hInstance, HANDLE hPrevInstance,
  142.                               LPSTR lpszCmdLine, int nCmdShow);
  143.  
  144.   1.5 Make sure that every source does include "v_defs.h".
  145.       I simply put the following:
  146.  
  147.         #if !defined (V_DEFS_H)
  148.           #include <v/v_defs.h>
  149.         #endif
  150.  
  151.       at the beginning of every V header file.
  152.  
  153.  
  154. 2. More Local Changes in the source code.
  155. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  156.  
  157.   2.1  File:  VAPP.H
  158.   ~~~~~~~~~~~~~~~~~~
  159.   Put the declaration of AppMain in a conditional compilation
  160.   block as in the following:
  161.  
  162.   #if defined (BUILD_V_DLL)
  163.     typedef int (*VEntryProc)(int, char**);
  164.     extern void  V_FUNC vRegisterEntryPoint(VEntryProc);
  165.     extern DWORD V_FUNC vGetApp();
  166.   #else
  167.     extern int AppMain(int, char**);
  168.   #endif    
  169.  
  170.   Remark:  
  171.   Your function AppMain can't be in the DLL, but WinMain calls
  172.   it (through CMain). At startup (WinMain) we give the DLL
  173.   the Address of our AppMain by the function "vRegisterEntryPoint" .
  174.              
  175.  
  176.   2.2  File: VAPP.CPP
  177.   ~~~~~~~~~~~~~~~~~~~
  178.         
  179.   2.2.1  Replace WinMain With DllMain
  180.   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  181.   Exclude WinMain when building the DLL. WinMain will be in a tiny
  182.   startup object file.
  183.   Add the function DllMain (needed in every DLL)
  184.  
  185.   #if !defined(BUILD_V_DLL)
  186.  
  187.   int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
  188.                      LPSTR lpszCmdLine, int nCmdShow)
  189.   {
  190.      return CMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow);
  191.   }
  192.   
  193.   #else
  194.  
  195.   BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID lpvoid )
  196.   {
  197.      return TRUE;
  198.   }
  199.  
  200.   #endif // BUILD_V_DLL
  201.  
  202.   2.2.2 Add 'vRegisterEntryPoint' and `vGetApp()'
  203.   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  204.  
  205.   - Add a global pointer-to-function `pVEntryPoint' - the one that
  206.     holds AppMain address.
  207.   - Add the function vRegisterEntryPoint.
  208.   - Add the function vGetApp.
  209.  
  210.   *******************************************************************
  211.   #if defined(BUILD_V_DLL)
  212.  
  213.   VEntryProc pVEntryPoint = NULL;   // holds the address of AppMain.
  214.  
  215.   void  vRegisterEntryPoint(VEntryProc p)
  216.   {
  217.      pVEntryPoint = p;
  218.   }
  219.  
  220.   // actually we should return vApp*, but VC++ complains that it
  221.   // can't find vGetApp when linking the application.
  222.   
  223.   DWORD vGetApp()
  224.   {
  225.      return (DWORD) theApp;
  226.   }
  227.  
  228.   #endif
  229.   *******************************************************************
  230.  
  231.  
  232.   2.2.3 Call the pointer to function instead of AppMain
  233.   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  234.   In function CMain, Call AppMain through the pointer `pVEntryPoint'.
  235.  
  236.   #if !defined (BUILD_V_DLL)
  237.   retcode = AppMain(argc,argv);   // call the app main program
  238.   #else    
  239.   retcode = (*pVEntryPoint)(argc,argv); 
  240.   #endif
  241.   if (retcode != 0)
  242.       return (retcode);
  243.  
  244.  
  245.   2.3 File: VSTARTUP.CPP  (new file)
  246.   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  247.   This File is not a part of the DLL but you must link it to your
  248.   program. Best to compile it and merge it with the import library
  249.   of the V DLL.
  250.   This file contains the modified WinMain and The global variables of V.
  251.  
  252.   The global data of a DLL is not exported, but we need this data in our
  253.   program. We must have access to `theApp' pointer and to the vColor
  254.   constants and strings. I still don't know how to access data in a DLL
  255.   so I duplicated this data. It is not critical at all.
  256.   Here is the source code of this file.
  257.  
  258. **********************************************************************
  259. // VSTARTUP.CPP
  260.  
  261. #include <v/v_defs.h>
  262. #include <v/vcolor.h>
  263.  
  264. class vApp;
  265. typedef int (*VEntryProc)(int, char**);
  266.  
  267. extern int   AppMain(int, char**);
  268. extern int   CMain(HANDLE , HANDLE , LPSTR , int );
  269. extern void  vRegisterEntryPoint(VEntryProc);
  270. extern DWORD vGetApp();
  271.  
  272. // This `theApp' belongs to the application (not to the DLL.)
  273. vApp* theApp = NULL;
  274.  
  275. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
  276.                    LPSTR lpszCmdLine, int nCmdShow)
  277. {
  278.    // pass the address of AppMain to the DLL.
  279.    vRegisterEntryPoint(AppMain);
  280.  
  281.    // initialize `theApp' of the application 
  282.    theApp = (vApp*) vGetApp();
  283.  
  284.    // call CMain as in the static library.
  285.    return CMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow);
  286. }
  287.  
  288.  
  289. // Define 16 standard colors for use by everyone
  290.  
  291. vColor vStdColors[16] =
  292. {
  293.    vColor( 0, 0, 0),    // vC_Black
  294.    vColor( 255, 0, 0),    // vC_Red
  295.    vColor( 127, 0, 0),    // vC_DimRed
  296.    vColor( 0, 255, 0),    // vC_Green
  297.    vColor( 0, 127, 0),    // vC_DimGreen
  298.    vColor( 0, 0, 255),    // vC_Blue
  299.    vColor( 0, 0, 127),    // vC_DimBlue
  300.    vColor( 255, 255, 0), // vC_Yellow
  301.    vColor( 127, 127, 0), // vC_DimYellow
  302.    vColor( 255, 0, 255), // vC_Magenta
  303.    vColor( 127, 0, 127), // vC_DimMagenta
  304.    vColor( 0, 255, 255), // vC_Cyan
  305.    vColor( 0, 127, 127), // vC_DimCyan
  306.    vColor( 63, 63, 63),     // vC_DarkGray
  307.    vColor( 127, 127, 127), // vC_MedGray
  308.    vColor( 255, 255, 255)  // vC_White
  309. };
  310.  
  311. char* vColorNames[16] =
  312. {
  313.    "Black", "Red", "Dim Red", "Green", "Dim Green", "Blue",
  314.    "Dim Blue", "Yellow", "Dim Yellow", "Magenta",  "Dim Magenta",
  315.    "Cyan", "Dim Cyan", "Dark Gray", "Med Gray", "White"
  316. };
  317. *******************************************************************
  318.  
  319.  
  320.  
  321. 3. Building the DLL.
  322. ~~~~~~~~~~~~~~~~~~~~
  323.   3.1 Some tips (not necessarilly related to V dll)
  324.   ~~~~~~~~~~~~~
  325.   - Compile with -DWIN32_LEAN_AND_MEAN
  326.     When you #include "windows.h" you include everything. 
  327.     since we do not use OLE, ODBC etc. there is no need to
  328.     include their headers.
  329.  
  330.   3.2 Compiler specific command line flags
  331.   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  332.  
  333.   Watcom C++:    wpp386 <your-org-flags> -dBUILD_V_DLL <file.cpp>
  334.  
  335.   Visual C++:    cl -c  <your-org-flags> -DBUILD_V_DLL <file.cpp>
  336.  
  337.   Borland C++:   bcc32 -c <your-org-flags> -DBUILD_V_DLL <file.cpp>
  338.  
  339.   When compiling the startup code (vstartup.cpp) compile it WITHOUT
  340.    -DBUILD_V_DLL. 
  341.  
  342.   - compile all V sources with the above options.
  343.   - compile vstartup.cpp without dll options.
  344.  
  345.   3.3 Linking the dll
  346.   ~~~~~~~~~~~~~~~~~~~
  347.   Watcom C++:  wlink sys nt_dll file { $(OBJS) } name v116.dll lib { ... }
  348.                wlib v116.lib +v116.dll
  349.                wlib v116.lib +vstartup.obj
  350.  
  351.   Visual C++:  SEE APPENDIX.
  352.  
  353.   Borland C++: The linker command line of BC++ is more complicated
  354.                Use the IDE to generate a makefile for the DLL, then
  355.                add the rule:
  356.                  "tlib BCV116.LIB +vstartup.obj"
  357.  
  358.                at the end of the dll target.
  359.  
  360.   - Copy the DLL to a directory listed in PATH.
  361.   - Copy the import library to your V LIB directory.
  362.  
  363. 4. Changes in The application code
  364. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  365.    NONE !!
  366.  
  367.  
  368. 5. Building the Application
  369. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  370. Instead of linking with the static library, link with the import library.
  371. Thats All !
  372.  
  373. Borland C++ issues a lot of warning messages. Add the option -w-inq
  374. to linker command line. The program is built and run OK.
  375.  
  376. Make sure that you compile your app with the same alignment as
  377. the DLL.
  378.  
  379.  
  380.  
  381. APPENDIX - Linking the DLL with VISUAL C++
  382. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  383. If you try to produce the dll after step 3.3 you get a lot of 
  384. error messages from the linker. It does not find the definition
  385. of some destructors.
  386.  
  387. Not sure, but it turns out that Visual C++ needs two kinds of destructors.
  388. The usual one and the one that is called when you delete a vector of
  389. objects (by operator delete[]).
  390.  
  391. It also turns out that The compiler automatically generate code
  392. for this destructor when you allocate an array of objects.
  393. for example:
  394.     new ClassName[2];
  395.  
  396. The trick is to supply a dummy function as follows:
  397.  
  398. void _dummy()
  399. {
  400.    new  ClassName1[2];
  401.    new  ClassName2[2];
  402.    new  ClassName3[2];
  403.    // ...
  404. }
  405.  
  406. This function is never called but when the compiler sees an array
  407. allocation it also generates the missing destructor.
  408.  
  409. We are not done yet. The problem is that not all V classes have
  410. a default constructor (or one with all default arguments).
  411. As usual the PreProcessor comes to rescue as follows.
  412.  
  413. *******************************************
  414. #define DUMMY_DEF_CTOR(ClassName)
  415.  
  416. #if defined (BUILD_V_DLL) && defined (_MSC_VER)
  417.   #undef  DUMMY_DEF_CTOR
  418.   #define DUMMY_DEF_CTOR(ClassName)  \
  419.     friend void _dummy();            \
  420.     protected: ClassName() {}        \
  421.     private:
  422. #endif
  423. ******************************************
  424.  
  425. We define the above macro as empty so that other compilers will
  426. not issue an error message.
  427.  
  428. For every V class that does not have a default constructor
  429. We must add the following:
  430.  
  431. class V_CLASS ClassName {
  432.     DUMMY_DEF_CTOR(ClassName)  // first thing !
  433.  
  434.     // ...
  435.  
  436. };
  437.  
  438.  
  439. Now we must supply a function _dummy(). I wrote this function in 
  440. "dummy.cpp" and put it in the V/MSVC directory. When compiling the
  441. V sources to produce a DLL, compile this file also.
  442.  
  443. **************************************************************
  444. // DUMMY.CPP
  445.  
  446. // include everything.
  447. //
  448. #include <v/v_defs.h>
  449. #include <v/vapp.h>
  450. #include <v/vawinfo.h>
  451. #include <v/vbaseitm.h>
  452. #include <v/vbasewin.h>
  453. #include <v/vboxlblc.h>
  454. #include <v/vbrush.h>
  455. #include <v/vbtncmd.h>
  456. #include <v/vcanvas.h>
  457. #include <v/vcbtncmd.h>
  458. #include <v/vchkboxc.h>
  459. #include <v/vclabelc.h>
  460. #include <v/vcmd.h>
  461. #include <v/vcmdpane.h>
  462. #include <v/vcmdprnt.h>
  463. #include <v/vcmdwin.h>
  464. #include <v/vcolor.h>
  465. #include <v/vcomboc.h>
  466. #include <v/vcpdc.h>
  467. #include <v/vdc.h>
  468. #include <v/vdebug.h>
  469. #include <v/vdialog.h>
  470. #include <v/vfilesel.h>
  471. #include <v/vfinddlg.h>
  472. #include <v/vfont.h>
  473. #include <v/vfontsel.h>
  474. #include <v/vframec.h>
  475. #include <v/vicon.h>
  476. #include <v/vkeys.h>
  477. #include <v/vlabelc.h>
  478. #include <v/vlistc.h>
  479. #include <v/vmemdc.h>
  480. #include <v/vmenu.h>
  481. #include <v/vmodald.h>
  482. #include <v/vnlprntr.h>
  483. #include <v/vnotice.h>
  484. #include <v/vnulldc.h>
  485. #include <v/vpane.h>
  486. #include <v/vpen.h>
  487. #include <v/vprintdc.h>
  488. #include <v/vprinter.h>
  489. #include <v/vprogrsc.h>
  490. #include <v/vradioc.h>
  491. #include <v/vreply.h>
  492. #include <v/vsliderc.h>
  493. #include <v/vspinc.h>
  494. #include <v/vstatusp.h>
  495. #include <v/vtextc.h>
  496. #include <v/vtextcnv.h>
  497. #include <v/vtexted.h>
  498. #include <v/vtextinc.h>
  499. #include <v/vthislst.h>
  500. #include <v/vtimer.h>
  501. #include <v/vutil.h>
  502. #include <v/vwin32.h>
  503. #include <v/vwindc.h>
  504. #include <v/vwindow.h>
  505. #include <v/vwinprdc.h>
  506. #include <v/vwinprtr.h>
  507. #include <v/vynreply.h>
  508.  
  509. void _dummy()
  510. {
  511.   new _appWorkTimer[2];
  512.   new vApp[2];
  513.   new vAppWinInfo[2];
  514.   new vBaseItem[2];
  515.   new vBaseWindow[2];
  516.   new vBoxedLabelCmd[2];
  517.   new vBrush[2];
  518.   new vButtonCmd[2];
  519.   new vCanvasPane[2];
  520.   new vColorButtonCmd[2];
  521.   new vCheckBoxCmd[2];
  522.   new vColorLabelCmd[2];
  523.   new vCmd[2];
  524.   new vCommandPane[2];
  525.   new vCmdParent[2];
  526.   new vCmdWindow[2];
  527.   new vColor[2];
  528.   new vComboBoxCmd[2];
  529.   new vCanvasPaneDC[2];
  530.   // new vDC[2];                   Abstract class
  531.   new vDebugDialog[2];
  532.   new vDialog[2];
  533.   new vFileSelect[2];
  534.   new vFindDialog[2];
  535.   new vFont[2];
  536.   new vFontSelect[2];
  537.   new vFrameCmd[2];
  538.   new vIcon[2];
  539.   new vLabelCmd[2];
  540.   new vListCmd[2];
  541.   new vMemoryDC[2];
  542.   new vMenuPane[2];
  543.   new vModalDialog[2];
  544.   new vNullPrinter[2];
  545.   new vNoticeDialog[2];
  546.   // new vNullDC[2];               Abstract class
  547.   new vPane[2];
  548.   new vPen[2];
  549.   new vPrintDC[2];
  550.   new vPrinter[2];
  551.   new vProgressCmd[2];
  552.   new vRadioButtonCmd[2];
  553.   new vReplyDialog[2];
  554.   new vSliderCmd[2];
  555.   new vSpinnerCmd[2];
  556.   new vTextCmd[2];
  557.   new vTextCanvasPane[2];
  558.   new vTextEditor[2];
  559.   new vTextInCmd[2];
  560.   new vThisList[2];
  561.   new vTimer[2];
  562.   new vWinDC[2];
  563.   new vWindow[2];
  564.   new vWinPrinterDC[2];
  565.   new vWinPrinter[2];
  566.   new vYNReplyDialog[2];
  567. }
  568. ***********************************************************************
  569.  
  570.  
  571.  
  572.