I am having trouble get a clear picture of the advantages/disadvantages of using Sharemem vs SimpleSharemem to pass strings between a main program and DLLs.
Here is the background for why I am looking into this: My main program is developed in XE2 64-bit (although I may upgrade to XE7) and the DLLs will either be developed with XE2 (or higher) or FPC 64-bit (the ideal scenario). The main program and the DLLs need to be able to pass strings contained in records. Ideally I would like to have the DLLs developed by people who may not have Delphi and it appears as though FPC supports Sharemem but not SimpleSharemem.
Are there performance differences between Sharemem vs SimpleSharemem? Are there other reasons to prefer one vs the other in the scenario I describe (aside from the apparent FPC support for Sharemem)?
Thank you!
Sharemem is the old way of sharing memory managers. It relies on a DLL being deployed alongside your application. SimpleSharemem is designed to work with FastMM which handles sharing in a different way from Sharemem. So for modern versions of Delphi that use FastMM as their memory manager, use SimpleSharemem.
Shared memory managers allow you to allocate memory in one module and deallocate in another, using the standard language heap functions like GetMem, New etc.
However, you are attempting rather more than this. You are hoping to share a memory manager between modules compiled by different compilers. Specifically Delphi and FPC. Delphi's ShareMem is designed to allow sharing between modules compiled in Delphi. Likewise FPC's ShareMem is designed to allow two FPC compiled modules to share memory manager. There is no support for sharing between Delphi and FPC modules.
Even further, you are hoping to be able to pass string objects between modules. This requires the implementation of the string object to be compatible across the interop boundary. That might be the case for Delphi's UnicodeString for XE2 and XE7 modules, but if so it is only by chance. There is no guarantee of that. Future releases of Delphi may change the implementation. And as for mixing Delphi and FPC strings, there's no reason to believe that they can be mixed. I doubt they can.
So my advise is to stop trying to use shared memory managers and stop trying to pass native language strings between modules compiled with different languages.
In order to pass text between modules in a mixed compiler environment you need to use valid types for binary interop. Typical approaches include:
Passing null-terminated C strings, PWideChar. Trivial when passing text in. When passing text out this becomes more difficult because you may need callee to allocate but caller to deallocate. Either export a deallocator or allocate on a shared heap, e.g. the COM heap.
Use the COM BSTR type. In both Delphi and FPC this is wrapped by WideString. This type is designed for binary interop.
My choice would be to use WideString.
Related
I understand from other posts here that "IMAGE_FILE_LARGE_ADDRESS_AWARE" may work to effectively expand memory availability in e.g. Delphi 2007.
I don't get this to work in Delphi6, is this indeed the case, or should it work? Or is there an alternative command that does the same thing?
If not, I may need to migrate to a later version of Delphi. Then, does anyone know what the most recent version of Delphi is that would easily allow me to migrate my existing code (ideally, my existing code, which is fairly simple Turbo Pascal-type code, would just work as is) AND would support the "IMAGE_FILE_LARGE_ADDRESS_AWARE" 'trick' to expand memory?
Many thanks!
Remco
You can apply the IMAGE_FILE_LARGE_ADDRESS_AWARE PE flag to a Delphi 6 application, but you must beware of the following issues:
The default memory manager for Delphi 6, the Borland memory manager, does not support memory allocations with addresses above 2GB. You must replace the memory manager with one that supports large addresses. For instance FastMM.
Your code may well contain pointer truncation bugs that will need to be found and fixed.
The same goes for any third party software that you use. This includes the Borland RTL and VCL libraries. I did not encounter many problems with these libraries, but it may be that your program uses different parts of the runtime libraries that have pointer truncation bugs.
In order to stress test your program under large address conditions you should turn on top down memory allocation. Do not be surprised if your anti-malware software (or indeed other system level software) has to be disabled whilst you operate in top down memory allocation mode. This type of software is notoriously poor at operating in top down memory allocation mode.
Finally, it is worth pointing out that large address aware cannot solve all out of memory problems. All it does is open up the top half of the 32 bit address space. Your program might require even more address space than that. In which case you'd need to either re-design your program, or move to a 64 bit compiler.
Is there is a way of exporting and using classes from another dll,
I have 2 dll's and I am trying to access classes in between, was wondering if this is possible.
There are a variety of ways to achieve this, including but not limited to the following:
Use runtime packages rather than DLLs. Then you can use any types, variables, etc. from another module. Note that this forces you to use runtime packages in all of your modules, and to compile all of the modules with the same version of Delphi.
Continue to use DLLs, but access the types via interfaces rather than Delphi classes. Interfaces, unlike classes, can be exported across DLL boundaries.
Continue to use DLLs, but access the types using unit scope procedures and functions rather than classes. This would lead you to an interface of the same nature as the Win32 interface.
Of the above options, they are arranged in order of decreasing convenience. The most convenient is to use runtime packages but that may place an undesirable constraint on you that all modules are compiled with the same Delphi version. Interfaces are usually more convenient to consume than a Win32 style interface, but there may be more programming overhead in setting up such an architecture. You'll have to make the choice that you feel best suits your needs.
If you can avoid using separate modules in the first place, and build everything into a single executable file, then that is far and away the most convenient approach.
If not, then does WinRT have its own Garbage Collector?
I ask this because I read this: "There's no need to manage the lifetime of underlying object. Windows releases the object when you're finished with the last of its class instances that you've activated." from MSDN.
They don't. WinRT doesn't use a garbage collector. Memory is managed with reference counting, IUnknown::AddRef() and IUnknown::Release(). Just like COM. And no, it isn't Windows that takes care of the counting, it is the language runtime support library. Javascript always used reference counting, C++ gets it from the C++/CX language extensions or by using smart pointer classes.
Summarization:
Please check the knowledgeable comments below.
==============================================================
I have seen the term of managed types mentioned in quite a few stackoverflow Delphi topics. For example, it is mentioned in topics of correctly initializing/finalizing. However, when I google managed types, it seems most links are related to C++, or .NET. For example, see the MSDN page. Could some one help to comment what are managed types defined in Delphi? Given that Delphi for POSIX/MacOS is being born, are managed types specific to Windows? Thanks for your effort and time in advance!
PS: Topics of correctly initializing/finalizing:
Which variables are initialized when in Delphi?
Are delphi variables initialized with a value by default?
How should I free an array of objects in a Delphi 7 destructor?
In Delphi 2009 do I need to free variant arrays?
In the context of Delphi, managed types are those types for whom the Delphi Compiler automatically generates lifecycle management code. This includes:
Strings
Open Dynamic Arrays
Records containing other managed types
Interfaces
(later edit) Anonymous methods
(later edit) Variants
Because managed types in the Delphi context are defined in terms of what the Delphi compiler generates, they're delphi-specific.
In the .NET world the developer doesn't need to manage the lifecycle of allocated memory because .NET provides an automatic mechanism for doing this: The Garbage Collector. But .NET includes the ability to work with things outside the CLR (example: using native DLL's that don't target the CLR). That code is usually called unamanged and unsafe.
In the context of .NET managed relates to what the CLR automatically manages, so that's .NET specific term!
See Barry Kelly's answer to a releated thread.
Since managed types are a language feature there shouldn't be significant changes on Mac OS et al.
I need to return objects from a DLL made in Delphi, to an app made in Delphi, too. The objective is to do a subsystem that can be modify in the future without to modify the main app. So, I imagine developing the subsystem in a DLL is a (good??) idea... i am programming in Windows XP, Delphi 7. I did read DLLs only return basic data type, but there must to be a way to do that...
Best regards.
I prefer to apply COM to such a model, which allows you to create external "objects" which you then can direct from within your application. Creating COM objects in Delphi is extremely simple, use your ActiveX creation methods to create an ActiveX library and then create COM objects. You then use the interface unit in your main application, and when you CoCreate an instance of the object it loads the appropriate DLL. The only tricky part of this is that your com objects must be registered on the system to function properly... which in the Win7/Vista world requires elevated access... although once this is done, it is seamless.
The BEST way is to use a COM wrapper as suggested by skamradt.
It is possible, but not a good idea to pass object references as pointers to DLL's. Refer particularly to Peter Haas's comments.
If you do pass an object from a Delphi DLL to a Delphi app you will have the following problems:
You must use the same version of Delphi for the app and DLL.
Both app and DLL MUST have the same implementation of the object - or at least identical layout of all fields in the class - OK if you are using standard objects such as TStringList.
You should use shared memory or runtime packages, otherwise you will get weird access violations.
I have had to maintain code where this was done - it was nightmarish as you couldn't change classes without a lot of re-compiling.
You can use interfaces and most of your problems, wrt compiler/rtl versions or even other languages just go away.
Delphi's interfaces are always IUnknown-compatible, which makes them compatible with most OO-enabled languages on Windows.
One thing to keep in mind, though: Don't use AnyString, stick to WideString, which is the Stringtype used by COM.
A platform- and language independent way could be to exchange serialized objects.
It has a performance impact, but it has advantages too: the DLL works without modifications with other languages and platforms like .Net or Java (via JNA Java Native Access). It does not depend on any special features of the operating system so it can as well be used on Linux or MacOS if you compile the library with Free Pascal.
For the serialization, you could use JSON or XML. There are open source libraries for Delphi, for example SuperObject and OmniXML.