PascalScript: how to correctly interpret Unit Importer output? - delphi

I'm giving a try to PascalScript, due to its features which could be very interesting in one of the programs I am developing.
Then, after following the awesome Lawrence Barsanti's introduction to PascalScript here, I came to have a look at the RemObjects Unit Importer.
Question is: I understood Lawrence's tutorial is focused on how to use PS without Unit Importer, but since I have rich and sometimes complex forms to work with, having a tool that already does the unit contents mapping could be a bliss.
Just, I can't figure out how to use Unit Importer output: is it a unit file to import into the project? What do I need to do to correctly use it?
Thanks.

The unit importer parses the interface section of a unit and generates an import unit for use by Pascal Script. It makes the Delphi code from the imported unit accessible to the Pascal Script interpreter. Include both units (the original and the generated one) in your project.
Instead of manually typing all the AddDelphiFunction calls to add your functions to Pascal Script, the importer generates code to call those functions for you. If you have USEIMPORTER defined in your project, then the import unit will automatically register the imported types, functions, and constants with the interpreter. Otherwise, you'll have to call the SIRegister_X function yourself when you have your own interpreter class ready.

Related

What are the fundamentals of optionally compiling a library or requiring DLL?

I would like to write a component with the ability for a developer to either require a DLL or include a unit in their app which compiles the library with the project, without the DLL.
For example, let's say it's called "MyLibrary". If I include MyLibrary in the uses clause, it will by default require that a DLL be distributed with the application. On the other hand, if another unit MyLibraryImplementation is in the uses clause, it will compile everything inside the app without requiring the DLL.
This component is inside a package installed into the IDE.
I'm not even sure the terminology for this, or anything about how to go about this. I'm very familiar with writing DLL's, and not looking for someone to write any full code.
What are the fundamental things I need to know to make this optional DLL possible?
You probably won't find the result very satisfying. Delphi cannot directly load classes from a DLL. Instead, you'll need to define some class in your MyLibrary unit. You'll also have to implement most of the methods there. You're welcome to make those methods be little more than stubs that delegate all the work to functions in the DLL, though. In the stub constructor, call a DLL function that allocates a data structure and returns a handle. In all three other stub methods, pass that handle to the corresponding DLL functions along with the methods' other arguments.
You'll essentially have three parallel implementations of the class:
The one in MyLibrary.pas that's nothing but stubs.
The one in MyLibrary.dll that backs the stubs.
The one in MyLibraryImplementation.pas that does all the same things as the DLL, but internally.
You can probably avoid duplicating too much, but not completely.
You don't need to do any of this, though. For years, Delphi has already offered comparable functionality built in: packages.
If your customers want to have your class's implementation live in a separate module, they can choose the "build with runtime packages" option in their projects' linker settings. Disabling that setting will cause your code to be compiled in to their EXE files instead, and they won't need to distribute the BPL file anymore.

What is required in Delphi 2007 to use Variant arrays?

I'm a newbie in Delphi, using Delphi 2007. I am learning things related to COM programming, in order to make a basic plugin to a program called Retail Pro. I have a little of background in .NET (C#, ASP), NetBeans (Java, JSF) and PHP.
Anyway, I'm following this intro tutorial to COM Programming :
An Introduction to COM Programming with Delphi
At second and third parts of the 5th lesson about Variant Arrays, there are sample codes to download. Here is the sample code of second part:
http://delphi.about.com/library/weekly/code/src122104_sample.zip
When I compile the code, it gives me a lot of errors of undeclared identifier (VarType, VarArrayCreate, VarArrayLowBound, etc). Is there some class to add in the uses section in order to be able to compile this piece of code?
The code is missing a unit from the uses clause. That unit is named Variants and contains all the symbols that the compiler cannot find. Add that unit and the code will compile.

What's the easiest way to access other .exe data in delphi?

I trying to implement some basic automated testing on a 10 million LOC project that don't follow good OO pratices (ex: isolating business logic into classes/units) with the DUnit that comes along with Delphi 2010. I can't do normal unit testing on this project since each part of business logic is spread across a dozens of interdependent units, these 'groups' of units are, however, centered around certain 'main business logic screens' (ex: all invoice logic related units are centered on the main invoice screen), and since those screens are classes I can do 'main business logic screen class testing' instead of unit testing, but those 'main screens' still need a lot of stuff that is created during the process startup.
So I need to both:
Be able to run the bad project's startup stuff
Be able to access its objects
The bad project already have some exported functions that return pointers that I can cast to access it's objects, but I'm unable to call them either way:
If I create the bad project as a child process of the test process, the startup code run fine, but I can't find a way to call the exported functions without complex IPC methods or substantial change on the bad project's structure.
If I load the bad project's .exe as an dll as with the LoadLibrary function, calling any function exported by bad project's result in access violation and/or segfault errors, even this simple procedure:
procedure Test; {safecall;} {stdcall;}
begin
showmessage('Yay!');
end;
How can I do both?
The approach you're talking about (using exported functions) is not going to fly. The simplest form of communication between two Win32 programs is to have them use SendMessage or PostMessage to talk to each other. Locating the window handle (usually by window class name) is step 1, sending a message is step 2.
Secondly, DUnit gets you nowhere near your goal, and TTestCase cannot be extended neatly to be a GUI Controller as that's not what it's for. It's for unit testing. Round peg, square hole. Write TTestCases for classes you can hive off and test, and use DUnit to provide test coverage for those parts of your system that you can provide test coverage for.
For UI testing, use a completely separate framework. There are two basic approaches done by Delphi programmers for automated integration tests of the sort you're proposing.
A custom hack job. Such is what you are describing. Inside Embarcadero, there exists a framework which is called Zombie, something Nick blogged about back in 2007. Its approach is based on several kinds of "primitive IPC", usually involving a Win32 SendMessage or PostMessage window message from outside the program to a window handle of a control inside the program. However, the internal code IS SIGNIFICANTLY MODIFIED to permit zombie testing. No you can't have Teh Codez, they're internal and proprietary to Embarcadero. But it does illustrate that the approach does work, and does not require rewriting the whole application or writing a huge number of mock-classes, like unit testing
would have done. If you want to go down the hack route, you will be writing your own User Interface Testing Framework, which should probably be completely separate from and use no DUnit code. You are welcome to try, but I'm telling you, it's a serious impedance mismatch. If I was starting my own custom framework in 2013, it would be DCOM based, because Delphi DCOM server code could be simply conditionally compiled into many programs, and DCOM would handle the function call "marshalling" details for you. I suspect I would get a year into the project, and I would give up, because in the end, I doubt I could make any system (DCOM or Win32 message based) pay off.
A complete external testing tool which you write test scripts in, like AutomatedQA/SmartBear TestComplete. Your tests would not be compiled into a delphi test program, but run inside TestComplete, and Pascal-like script syntax is just one of the available options for writing your test scripts.
We have had the same problem here. It looks like you really need a delphi library project (*.dll) for the export functions to work, (I suspect no initalization of the framework takes place when calling the function directly on an executable, no warranties).
NOTE: We are still using Delphi 5, so no dunit intergration here.
The solution we've used is to adding the dunit sources to our project (the .exe project) with a conditional DEFINE, and use this conditional define in the startup unit.
Sample startup code from our application:
if ComServer.StartMode <> smAutomation then
begin
OurApplication.Login ;
end;
{$IFDEF _AS_TESTRUNNER_}
GUITestRunner.RunRegisteredTests;
{$ELSE}
if OurApplication.HasStartCommands then
begin
Application.ShowMainForm := False ;
end
else begin
if ComServer.StartMode = smAutomation then
Application.ShowMainForm := False
end;
Application.Run;
{$ENDIF}
OurApplication.Finalize;
When I use the _AS_TESTRUNNER_ conditional define, I must login first so our app (and db connections) get initialised. Followed bij the GUITestrunner of DUnit.
Testcases can be registered in the initialization part exactly as in the examples.
Works like a charm.

Is dynamic class loading possible in delphi

I have a environment and I want to know that if I write code in this environment is it possible to save>compile and use that code?
whats is more is that I want the environment to be able to call function in this code and for the code to be able to call function in the environment..
I think there was something called class loaders in java that allows you to do this.. can I do this is Delphi and what is the best way to go about doing this?
(just in case anyone says about putting it in there to start with its for a game for kids, they will just write a section of the code dealing with simple logic and variables and have calls to methods that are in the environment that move a virtual robot)
Delphi doesn't have any facilities for compiling code at runtime, but there are a fair number of scripting languages that do. Take a look at PascalScript from RemObjects, for example. It can do most of what you're looking for, though it doesn't have any facility for creating new classes. I don't think any script engine does. But it can import existing ones from Delphi and create new Pascal functions and procedures for your program to interact with.
You should be able to do what you need to do using paxCompiler.
If you absolutely need compiled code, you can use freepascal to generate a dll and then load this from delphi. Yes, should be nice to' have a free version of commandline Delphi compiler.

Virtual Library Interfaces for Delphi/Win32?

I read this article and find the concept of Virtual Library Interfaces nice for runtime loading of DLLs. However it seems that they aren't available for Win32. Is this true? And if so: Why? I don't see what would tie the idea to .NET.
EDIT: I'm mostly rephrasing here what Rob already wrote. :-)
I'm not after plugins or similar - it's about plain old Win32 DLLs. What appeals to me is the idea to let the compiler deal with all the details of loading a DLL at runtime - no need to call GetProcAddress for every function in the DLL etc.
It seems to me like the three answers so far have completely missed the point of your question. That, or I have. You're asking why Win32 Delphi doesn't have something like the magical Supports function that Hallvard's article talks about, aren't you? Namely, a function that, given the name of a DLL and the type information of an interface, returns an object that implements that interface using the standalone functions exported from the DLL.
Hydra seems to be all about calling .Net code from a Win32 program, not about importing functions from a DLL. TJvPluginManager requires that the plug-in DLLs export a special self-registration function that the manager will call when it loads the DLL, and the function must return an instance of the TJvPlugin class, so the plug-in DLL must be written in Delphi or C++ Builder. The Supports function, on the other hand, works with any DLL written in any language. You could use it on kernel32, if you wanted.
I don't know why Win32 Delphi doesn't have such a thing. Maybe CodeGear didn't see much demand for it since Delphi and Turbo Pascal had already gone for so long without it.
It's certainly possible to write a function that works like that, and I don't expect it would be any harder to write than the .Net version must have been, unless Microsoft's .Net libraries already provide most of the pieces and Delphi just wraps them up into a convenient-to-call function that looks like the several other overloaded versions of Supports that Delphi has had for years.
There would be a few steps to implementing that function in Win32. (I'm providing only a sketch of what's necessary because I don't have a running copy of Delphi handy right now. Ask nicely, and maybe I'll find more details.) First, you'd need to make sure that type information for an interface held, at a minimum, the undecorated names of its methods. Then, Supports would need to generate a function stub for each method in the interface (besides _AddRef, _Release, and QueryInterface). The stub would go something like this, assuming the calling convention is stdcall:
asm
// Pop the return address,
// discard the "this" pointer,
// and restore the return address
pop eax
pop ecx
push eax
jmp AddressOfFunction
end;
As Supports generated each stub, it would fill in the actual function address, gotten from calling GetProcAddress with the name of the corresponding interface method. The stdcall calling convention is easy to wrap like that; cdecl is a little cumbersome; register is a pain in the neck.
Once it has all the stubs generated, it would need to generate an "object" that looks like it implements the given interface. It doesn't have to be an actual class. At compile time, Supports doesn't know the layout of the interface it's going to be asked to implement, so having a class wouldn't accomplish much.
The final step is to provide implementations of the _AddRef, _Release, and QueryInterface. _AddRef would be unremarkable; _Release is where you'd call FreeLibrary when the reference count reached zero; QueryInterface wouldn't do much at all, except claim that it supports IUnknown and the interface given to Supports.
Delphi used to come with a sample program that demonstrated implementing an interface without any classes at all. It was all done with records and function pointers (which is all an interface ultimately is, after all). Delphi also came with the corresponding code to do it with classes, in part to show how much easier Delphi can make things. I can't find the name of the demo program now, but I'm sure it's still around somewhere.
There are a number of Win32 options for this type of functionality. Project JEDI has an open source plugin system as part of the JVCL that loads either DLLs or packages, and can include forms and whatnot as additional functionality.
There are also a number of commercial products available, including the TMS Plugin Framework and RemObjects Hydra.
This is nothing new or special. The article's just talking about plugins. Native code's been able to do plugins for years. The only special thing about P/Invoke is that it allows native code and .NET to talk to each other in a plugin system, and the little trick where "the DLL can be seen as a singleton object that implements the interface [so that] you can use the Supports function from the Borland.Delphi.Win32 unit to check if the DLL and all the methods are available."
If you want to do what the article's talking about in Delphi for Win32, look at the LoadLibrary, GetProcAddress and FreeLibrary Windows API functions. If you absolutely must have an interface like the article describes, you have to write it yourself, either in the DLL (if you wrote the DLL yourself) by writing an exported function that returns an interface, or in the calling app, by writing a function that uses GetProcAddress to create an interface dynamically. (Caution: this requires mucking around with pointers, and is usually more trouble than it's worth.)
Your best bet is probably just to do what Tim Sullivan mentioned: use TJvPluginManager from the JEDI VCL if you only need native code, or Hydra if you have to talk to .NET assemblies.
I've used Hydra myself for a Delphi only solution (i.e., didn't interface to .NET) and it works great for that too. It's easier to use and adds some niceties, but I think that it's basically implemented the same way as the "roll-your-own" plugin framework that is well-described in this article:
http://www.saxon.co.uk/SinglePkg/
I would look for a plugin framework that's interface-based (like Hydra and the "roll-your-own" system in above paragraph), rather than one that simply sends messages between apps.
There is a Delphi plugin framework on sourceforge, don't know whether it's the same one as in JEDI project or not: http://sourceforge.net/projects/rd-dpf
There are also a couple of other commercial solutions, one of which is Dragonsoft's:
http://www.dragonsoft.us/products_dsps.php
What is wrong with doing this with simple com objects? Declare a simple interface that all of your plugins implement, and require that each com object include an exported function that returns its class guid. Then using the "plugins" is as simple as walking thru the plugins directory looking for DLL's which expose the special registration function, invoking it and then using the class guid to then invoke the com object.
I used something like this in a WIN32 commercial application with great success. The advantage was I could switch plugins in and out at will (provided of course the application wasn't running to remove existing ones), the magic was all in the interface that each one implemented.

Resources