Beyond the Limits
Pictures and Dynamic Libraries: A Poor Man's Plugin, Part II
Issue: 4.3 (January/February 2006)
Author: Didier Barbas
Article Description: No description available.
Article Length (in bytes): 5,794
Starting Page Number: 42
RBD Number: 4320
4320.sit Updated: Monday, January 16, 2006 at 12:55 PM
4320.zip Updated: Monday, January 16, 2006 at 12:55 PM
Related Web Link(s):
Known Limitations: None
Excerpt of article text...
In my last column we saw the makings of a dynamic library and an RB class that could replace/stand in for the missing Picture class in console applications. Rather than bore you with more detailed accounts of how fPic's innards were put together, let's wander around and look at other pieces of the puzzle: ancillary tools used, and sometimes written, to help build a dylib/RB class pair. This should give you enough information to build your own, and possibly use such dylibs in other languages. As I said in the previous column, building a dylib is best done with XCode. It does allow and/or require some tweaking, like setting up the necessary includes, the optimization level, or the instruction scheduling (for G4 or G5 processors). However, you might want more, like automatic packaging of the end-product -- things that can be easily automated and called from XCode as post-flight scripts. Also, while coding the RB end of the dylib, some repetitive tasks can be made easier with a dash of RB. Point in case: writing Declares. fPic has a lot of functions and writing the RB methods that matched these proved to be tedious, as every method required me to convert one or more C function calls into a Declare. As there are currently around 50 functions, you can imagine how boring it would become. So I wrote a small app that did the conversion for me. Fortunately, fPic's C code mainly uses void, int [*] and char [*], so writing a helper application that translated a C function declaration into an RB Declare was easy enough. This saved me a lot of typing. Let's see how it's done. Converting C method declarations into Declares void rot180(char *mb, int width, int height) < This translates into: Declare Sub rot180 Lib manip (mb As Ptr, width As Integer, height As Integer). So we need to capture the following parts: void: This tells us whether this is a Sub (no return value, like with our example) or a Function (and which kind of return value). rot180: The name of the method we will be calling. (char *mb, int width, int height): A list (or not) of parameters with, for each parameter: a type, a possible * marker, and the name of the variable. This translates, roughly, into the following regular expression: ^[ \t]*(\w+)[ \t]+(\w+)\(([^)]*)\)[ \t]*\<$. We'll see in a moment what it does. First a word on types and equivalencies. This is a question that crops up often on the mailing lists, and Brady Duga has provided a great summary at http://ljug.com/table.php that explains which RB type to use in connection with which C type. Byref precedes a variable name when passing a reference to the variable, e.g. int *height is Byref height As Integer, except for buffers/strings, where Ptr takes care of the referencing: char *mb is mb As Ptr. Now, back to the regex. The first part, ^[ \t]*(\w+), catches the return type, possibly preceded by spaces and/or tabs. The type will be stored in $1, a.k.a .SubExpressionString(1). Then, [ \t]+(\w+)catches the method name, stored in $2. \(([^)]*)\) catches the parameters, if any, in $3 and the last bit, [ \t]*\<$ just checks that this was a complete definition. I always open my curly bracket pairs on the first line, so this was a good way to check. Your mileage may vary on this point. If we have a match, $1 and $2 can be put to work very quickly. If the return type is void, then it is a Sub and there will be no return type; if not we'll have to return the equivalent type in RB and declare the method as a Function. Then comes the name, in $2. So far we have Declare (Sub|Function) [name] Lib manip () (As [type]). $3 is a bit trickier to handle. We have to split it by "," and work on each slice: determining the type, whether it's a reference or not, and the variable name. Insert that between the parentheses, and we have a fully functioning Declare. Paste the end result into RB, and start the real coding. Since this is a small application that you'll use frequently, it looks like a good idea to add a few lines of code that test the clipboard: if we have a C function declaration in it when we switch (from XCode, where we copied the string) to the helper app, paste it into the "Source" EditField, run the conversion code, and put the result back onto the clipboard. One keystroke and we're done. See the sample application: it's all there! Post-flight packaging One of the nifty things that can be done in XCode is running scripts if the build was successful. I am a Bash fellow, so that's what I use to write my post-flight scripts, but you could do that in RB, Python, Java, or Applescript. Usually, the built dylib is in a subfolder called build. In fPic's distribution package I have the dylib itself, two sample projects, a bunch of pictures, the documentation, and a folder containing another functioning sample, OnDemandPDF. We want to make a tar/gzipped archive of all this, and upload it to our web site. Here's what the script looks like: #!/bin/sh cd ~/Documents/rb\ projects/fPic/fPicTrial ; tar -czf fPicTrial.tgz ../build/manip.dylib "fPic tester.rb" jpeger.rb install.sh "Manip Dylib and fPic class doc.rtfd" tux-abul.jpg Xantung.pdf Tasha_Extrude.tif ~/Sites/OnDemandPDF/ ; curl -T fPicTrial.tgz ftp://login:password-at-sungnyemun.org/www/downloads/ What this does is actually quite simple: it enters the fPicTrial folder, where most of the files are, and builds a gzipped tar archive called fPicTrial.tgz. When it's done, curl puts the archive on my server's downloads area. This is where you can get fPic's current release: http://sungnyemun.org/downloads/fPicTrial.tgz. Depending on your needs you can add more tasks, like versioning your builds (incrementing a build number in a file and adding that to the executable's name) or sending an alert to a list of people by email.
...End of Excerpt. Please purchase the magazine to read the full article.
Article copyrighted by REALbasic Developer magazine. All rights reserved.