1

in mine project i have a Windows application and a dll. I have wrote dll so:

library MyDLL;

uses
  System.SysUtils,
  System.Classes;

{$R *.res}

function Prova: string; export;
begin
  result := 'prova';
end;

exports Prova;

begin
end.

and in main program i have called routine so:

unit FrmMain;

interface

uses
 // declaration uses // 

function Prova: string; external 'MyDLL.dll';

type    
 // declaration type //

implementation

begin
  ...
  TAdvEdit1.Text := Prova;  // [1] // 
  ...
end;

end.

When i compile all project not is reported error, and status report SUCCESS, but application not start. If i remove the line [1] then it works correctly. In general, application not start when i call the function Prova. What i can solve this problem? Thanks very much.

Marcello Impastato
  • 2,263
  • 5
  • 30
  • 52
  • 3
    When you create new dll porject, there is a comment in dpr file about using `ShareMem` module. Have you read it? – teran Nov 11 '12 at 12:06
  • 2
    Did you read the commetblock on top of a new created DLL-Projekt? – bummi Nov 11 '12 at 12:06
  • To add to the two previous comments, see "Writing Dynamically Loaded Libraries" topic in the help, especially the [Shared-Memory Manager](http://docwiki.embarcadero.com/RADStudio/XE3/en/Writing_Dynamically_Loaded_Libraries#Shared-Memory_Manager) section. – ain Nov 11 '12 at 12:08
  • Ok, i have added sharemem as first unit in both projects but not solded yet. Before to run, i have builded all project again. – Marcello Impastato Nov 11 '12 at 12:18
  • I hope TAdvEdit is just a typo ;o) – Sir Rufo Nov 11 '12 at 23:17

2 Answers2

3

The behaviour you describe is what happens when your application fails to load. When run from the debugger you get a silent failure. When run without a debugger you will see an error message, "Application failed to initialize...". This will give details.

In your case it seems that the likely cause is that the dependency of the DLL cannot be resolved by the library loader. That's why the app runs when the call to the external function is removed. When you remove that call, you also remove the dependency on the external DLL. Solve the problem by making sure the DLL can be loaded. For example place it in the same directory as the executable.

The silent failure from the debugger is rather frustrating. Once you have experienced it a few times you'll know what to do - run without the debugger to find out what's really going wrong.

I also recommend that you don't pass managed Delphi strings across module boundaries. That will force you to use the same compiler for both executable and DLL. If you are going to accept that constraint then you may as well use packages. As your code stands, it would need to use ShareMem to work. But I don't recommend that.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    I get an error *"The program can't start because MyDll.dll is missing ..."* when I run the executable in the debugger, instead of a silent fail. Is there a setting for this? – Sertac Akyuz Nov 11 '12 at 14:32
  • @Sertac I don't know. I'm sure at times in the past I've seen loader errors from running with debugger too. Perhaps it's OS or 32/64 bit related. Not sure. i've definitely been stumped by the silent fail a few times of late. – David Heffernan Nov 11 '12 at 14:37
2

Your program and your DLL have separate memory manager. As a general rule memory allocated from DLL should not be used inside your application (the opposite is also true). Where the allocation comes from? In Delphi "string" is managed type i.e. when you assign some text to a string variable (in your case result := 'prova'), Delphi (behind the scene) allocates memory for that string using DLL's memory manager. Then, for example, if you assign other text value within your main application, the reallocation uses application's memory manager which is bad i.e. app's MM is touching memory that it hasn't allocated itself.

To solve this issue you have to include "SimpleShareMem" (Delphi >= 2010 IIRC?) unit as the first unit of your USES clause in the application (.dpr file) AND in the DLL:

library MyDLL;

uses
  SimpleShareMem, // **MUST BE THE FIRST UNIT**
  System.SysUtils,
  System.Classes;
...


program YourApp;

uses
  SimpleShareMem, // **MUST BE THE FIRST UNIT**
  // declaration uses // 

An example of this approach can be found in "Start > Programs > Embarcadero RAD Studio > Samples > Delphi > RTL > SimpleShareMem"

You can also use PCHAR to transfers strings between DLL and the APP.

iPath ツ
  • 2,468
  • 20
  • 31
  • Hello, yes i have done so too. Replace sharemem with simplesharemem, before to run application tell me that not is possibile change memory manager. But application run without called to prova function. If i try to call prova function then application not run. – Marcello Impastato Nov 11 '12 at 12:26
  • @Marcello, by "not run" you mean crashes or it does not compile at all? – iPath ツ Nov 11 '12 at 12:27
  • i not run from run, before i compile all; and compilation not give problem – Marcello Impastato Nov 11 '12 at 12:30
  • Ok solved now finally. The problem was that dll not in same directory of executable file. Now i try to solve too this problem. Thanks very much. – Marcello Impastato Nov 11 '12 at 12:40
  • @Marcello, very unexpected and far away from my answer ;) Here is a good topic to read for your case: http://stackoverflow.com/questions/13269169/how-to-use-a-dll-outside-of-the-system-path – iPath ツ Nov 11 '12 at 12:43
  • 1
    @Marcello, also note SimpleShareMem must be the first unit in your application's file (.DPR), not in the form's file. I edited my answer. – iPath ツ Nov 11 '12 at 12:47
  • 2
    @Marcello Why did you accept the answer? Your problem was that the loader could not find the DLL. You should answer your own question and accept that. Accepting an answer that doesn't answer the question is not ideal. – David Heffernan Nov 11 '12 at 12:51
  • @Marcello, David Heffernan is right, I didn't noticed you have accepted. My answer in fact does not solve your main problem. – iPath ツ Nov 11 '12 at 12:53
  • 1
    Hello David, i have accepted the answer becouse effectvely the thing that i have forget to do was add the sharemem / simplesharemem unit to both project. Me not done it to begin, and sincerly not read about note from BDS. After i understood too becouse not start, becouse need to do run parameters, and set from there the application path. – Marcello Impastato Nov 11 '12 at 13:00
  • @iPath - The question you linked won't help here since the dll is statically loaded. – Sertac Akyuz Nov 11 '12 at 14:11
  • you could also use WideString instead of String and get rid of SharedMem http://stackoverflow.com/questions/12954973/putting-classes-in-a-dll/12959895#12959895 – Sir Rufo Nov 11 '12 at 23:00