From: Gil B. <gba...@al...> - 2017-02-03 20:44:26
|
I know it has been a while since I gave an update on this topic so I've included the last one I posted to refresh everyone's memory. As noted in the last post, I was at the point of writing my own C++ code for some native methods. I chose to implement the methods that I had previously written using GCI to change the color attributes of the Windows console. Even though this is somewhat obsolete with Windows 10 - ANSI escape sequences are again supported to do color highlighting - it has always been my goal to "complete" the original effort so that it would work on 64-bit versions of ooRexx as well (GCI is limited to 32-bit). By writing native methods, I would be able to compile them for both addressing modes. By keeping the same interfaces, I only needed to replace the GCI-based methods in the Class definition with the new native method definitions (one liners!). There are three methods involved, one that takes no arguments but returns a value, one that takes the value returned by the first method and returns a (different) value, and finally one that again takes the value returned by the first method but returns nothing. Using Rony's examples and the work I did for the GCI-based methods, it was fairly straightforward to come up with the C++ code and the .def file. I took part of Rony's makefile and was able to get a 32-bit DLL to build! Making the noted changes to the Class definition, my test program ran successfully! I still had lots of questions about the makefile contents so I did some research which included looking at the samples\native.api folder that is installed with ooRexx. This example contains code and a makefile which is very different than Rony's. It distinguishes between building a debug version and a "release" version while Rony's has a choice between 32- and 64-bit versions. I decided that my "general" build process should allow for all four combinations of addressing mode and debug/"regular" versions. I also read that building "out of source" is recommended - doing the build in an empty directory rather than the directory where the source files are located. The advantage cited was to allow the deletion of the build files w/o the possible accidental loss of a source file. For me, this structure would also allow me to build both 32- and 64-bit versions without having to adopt a naming convention or renaming the .dll since each version would be in its own directory. I spent some time writing a Rexx program to automate the process: check that the specified build "type" was valid, creating the appropriate subdirectory if needed, passing the correct argument to the vcvarsall.bat file to set up the compiler/linker for the correct target addressing mode, setting an environmental variable for use by the makefile to control the flags for debug/non-debug compiling and linking, and finally running nmake. After tweaking the makefile so that it reflected the fact that the source files were now in the parent directory, I got it to build a 32-bit .dll which worked with my test program. However, when I tried to build a 64-bit .dll, I ran into a (compile) problem. It turned out that the first method returns a value called a handle which is more like a pointer than an integer. In 32-bit mode, pointers and integers are the same size but that is NOT true in 64-bit mode. So I needed to change my code to use the new "types" added to the ooRexx API. After changing the type from "int" to "uintptr_t" wherever the handle was referenced, the compile was clean in both 32- and 64-bit versions. I was able to install the latest 64-bit ooRexx 5.0.0 beta and verify that my test program, using the 64-bit .dll, ran successfully. So goal accomplished! I still need to decide on the structure and contents of the makefile however. There are flags which are now considered obsolete which I want to remove and I need to put in the logic for debug/regular build flags. I'd like some opinions on structure as well. Rony's sample makefile does the compile and link back-toback. The sample in the native.api directory, does them separately. I believe the terminology is "target" and "dependency" so that the .exe or .dll "target" is dependent on the .obj and the .obj "target" is dependent on the .cpp. Having separate "rules" would let you do just the compile or just the link or both if you desire. In complex cases, this might be advantageous but for simple bits of code (like mine), running both commands is easier to understand. I've also written a simplified version of my Class that only uses two (native) methods that might be suitable for inclusion in the native.api samples. Once I decide on the contents of the makefile, I'll make the pieces available for review. Thanks for reading this far! Comments or questions are welcome. PS I've started to look at CMAKE but haven't yet done any experimenting with it so far. On 9/17/2016 1:29 PM, Gil Barmwater wrote: > Success! I have now been able to build and run Rony's examples from > last year's Symposium. Here is what I did to get there. > > Having discovered that my Visual Studio Express installation was > incomplete(!), I decided to "start over" rather than try to "fix" it. I > uninstalled Visual Studio from Control Panel -> Programs and Features. > There were messages about third party installers possibly leaving items > still installed but I did not see anything obvious. There were items > that had the same date as when I had installed Visual Studio but they > might have just been updates so I did not uninstall them. In any case, > they did not affect what I did next. > > I went back to Rene's presentation and clicked on the link he supplied > for Visual Studio Community. This seems to be the most recent free MS > Visual Studio product and, although Express is still supported, I > suspect future support will be concentrated on Community. And I wanted > to be sure that the ooRexx project would build correctly (when I get to > that point) with the newest free Visual Studio. I selected the custom > install and picked just one item under Programming Languages - Visual > C++/Common Tools. I also selected the Tools (1.4.1) & Windows 10 SDK > under Windows and Web/Universal Windows Application Development because > I seem to remember comments on this list in the past to the effect that > it was needed for something (perhaps debugging?). So I only had two > items checked in the custom dialog. The install process started and as > packages finished downloading, they were installed in parallel. Even so, > the download portion took over an hour and then the remaining installs > and updates took another hour! Glad I didn't select anything else from > the menu! > > I located the "shortcut" for a command prompt which would run the > VCVArsAll.bat and it ran successfully so I knew I now had the C++ tools > I needed. I then found the full path name to that .bat file and put it > in a short .cmd file in the folder where I had put the source for Rony's > examples. When I ran the that .cmd file and then the NMAKE command he > documented in his presentation, the DLLs were built and I ran the 4 test > cases he supplied without error. > > The next step for me is to experiment with writing my own native methods > to be sure I understand all the parts I need - a .cpp file, a .def file > and a makefile - to get a DLL I can reference from a ::method statement. > > So it will be a while before I am ready to get all the other tools to > attempt to build ooRexx from an SVN checkout. I'll post again when I'm > at that point. > -- Gil Barmwater |