1

I'm getting an access violation when I try to link to a function within a DLL file. DLL was made in Delphi 6 and we are upgrading to Delphi 11 (wild jump I know). So the code once upon a time worked and somewhere in the many changes to Delphi has come crumbling down. The Delphi environment is running on a Windows 10 machine. The DLL in use has been compiled and built within Delphi 11 (though components have changed). Delphi claims that it can compile and build, if that is where this issue possibly lies I can get more code as I have the source (and project files) for the DLL.

procedure TForm1.Button1Click(Sender: TObject); type TShowUserList = function : TForm; stdcall; var LHandle: THandle; LUserList : TShowUserList; LForm : TForm; begin LHandle := LoadLibrary('E:\D11 Projects\Test Dll\Win32\Debug\BOUsers.Dll'); if LHandle <> 0 then begin @LUserList := GetProcAddress(LHandle, 'ShowUserList'); if @LUserList <> nil then begin LForm := LUserList; //Here is where error shows, doesn't even get to the ShowUserList function end; end; end; 

When debugging, when I get to LForm := LUserList, LUserList is an 'inaccessible value'. Which would make sense as to why the error is occurring.

And within the BOUsers.dll is a UserList form,

FUNCTION ShowUserList : TForm; BEGIN IF NOT G.FormExists('UsersListForm') THEN BEGIN UsersListForm := TUsersListForm.Create(Application); Result := UsersListForm; END ELSE Result := G.ReturnForm('UsersListForm'); END; EXPORTS ShowUserList; 

Debugging doesn't even enter here (I have made sure debugging is enabled for the dll, though it seemingly was by default). I'd be slightly happy if I could get into this code and debug!

I'm aware there isn't the full amount of error handling (not that there was much on the D6 version). However this is just a test project to help figure out the issue in the main application, I can add it if needs be though.

My expectation is that LForm would be the UserListForm within the dll and that I'd be able to display it within a window pane, debug it for issues and use it as expected.

I've tried to look through various similar questions on StackOverflow (though if I've missed one feel free to link it and I will look through it). Copied the example embarcadero supplied.

Honestly, haven't worked with DLL's before past applications were all units and forms within the exe basically.

4
  • 1
    The EXE's TForm is very different from the DLL's TForm. Commented Jun 12, 2023 at 11:37
  • Is that the case even if the DLL's been compiled and built in Delphi 11? Commented Jun 12, 2023 at 11:42
  • 1
    @TedEdGo Yes. It is typically unsafe to use non-trivial data types, like VCL objects, across a raw DLL boundary. If you want to directly use a TForm object across the boundary, you need to enable Runtime Packages in both DLL and EXE, and also compile both in the same compiler version. Otherwise, you would need to re-design the DLL to abstract the TForm access behind something that is compatible with C, either by using plain flat functions, or a COM interface. The code shown would not work safely as-is even if the EXE were written in D6 without using Runtime Packages. Commented Jun 12, 2023 at 20:10
  • 1
    Wondering how the heck it worked in the first place but thanks for the explanation. Think you've helped me get through a few humps with this migration malarkey. Only about 30 DLL's to get through re-designing / where applicable re-integrating with the main application as no-one here could answer why some of the DLL's were made. But thank you very much for your help here and with the other question, it is much appreciated. Commented Jun 14, 2023 at 14:01

1 Answer 1

0

You didn't mention it, but what OS are you running this on? Win XP by any chance? Are you trying to migrate the app to Win 10 or 11?

I'm asking because I'm not sure D11 will even run in Win XP, so I'd be very surprised if you could access a DLL created in D6 from code written in the latest version of Delphi (D11).

I think your best bet is to get the source code for the DLL and rebuild it in D11 first. Short of that, if it's from a 3rd-party vendor, look into getting a newer version.

If you don't have the source code, then I'm not sure what to suggest other than rewriting it or replacing it with an equivalent library. (Surely someone has written something similar in the past 20 years!)

At my last job, I was given the task of migrating a Delphi app from XP to Win Server 2016. They thought it would be a simple recompile, but that didn't work as the DLL wouldn't run in Win10. We were not compliant with the vendor's licensing terms anyway, and the vendor wanted to charge us an arm and three legs for a newer solution. I eventually proposed we replace the DLL with a component library written natively in Delphi that ultimately did the job much cheaper and WAY faster.

ADDED (per your request below): you didn't ask for this exactly, but since you have the source code, you might consider refactoring by turning these DLLs into micro-services using a locally hosted REST service (ie, inside of your intranet). That would work great for things where timing isn't an issue and would simplify the deployment to other machines (if that's even a need) where the DLLs would require more attention. There are lots of libs that can be used to build services with Delphi; I'm partial to TMS XData. There are a couple of online courses they sell that take you step-by-step through the process. (It's part of their Biz Components lib.) Unless you're returning PODOs from the DLLs (not likely) then it should be really straightforward to migrate them to a micro-service architecture.

Sign up to request clarification or add additional context in comments.

11 Comments

I didn't mention that! Whoops, I'll edit the answer. But I am running Windows 10. So Delphi 11 is fine on that front. I've also compiled and built the DLL in Delphi 11 and it say's it's fine. Whether that is actually the case is another matter. Ideally this would be built for Windows 10 (and 11 down the line). All dll's are inhouse built so I have the source still. The only thing's that have changed in them is a few visual controls but I'm not even getting that far yet :( I'll amend the question to include this extra information. But migrating is a pain in the backside right!
Can you update the answer with the new information? But *** *** *** *** *** *** *** *** *** *** without *** *** *** *** *** *** *** *** *** *** *** "Edit:", "Update:", or similar - the answer should appear as if it was written right now.
@DavidSchwartz "I'm not sure D11 will even run in Win XP" - correct, the IDE itself won't, but that is not a factor here. "I'd be very surprised if you could access a DLL created in D6 from code written in the latest version of Delphi (D11)." - yes, of course you can. Provided the DLL is designed so its interface is compatible across different compilers. Which, unfortunately, this DLL is not, it seems.
I got the registration side (had to do that way too much at the last workplace). But seems like the solution will be a mix of Micro-services, redesigning DLL's and re-integrating some of the DLL's back into the main application as they don't really need to be a DLL. Didn't think of using Micro-services, though I was also trying to minimise the changes made to the system (as much as possible during the migration at least). Seems that won't be the case so a good ol' hammer and get stuck in approach seems best fit. But thank you for your help.
@DavidSchwartz Might be worthwhile adding information of micro-services to the original answer as that with the combination of redesign / removal of some is the end result (allows SO to have an answer). Also, I can't answer why forms and such as attached to a DLL process, and nor can anyone who works here. An undocumented decision of a bygone era! :)
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.