In both .NET and Java, when you create an object from (link to or load) a DLL written in one of those managed languages, you are actually creating a new instance of a class within the DLL, rather than creating an instance of the DLL itself. Why? Because in such cases it is handled by the managed platform (.NET/Java) rather than by the OS. In reality, though, it is the managed platform by which the program communicates with the operating system, which subsequently handles the library. However, when writing a .NET/Java application which loads a DLL created in some other language such as a C/C++ based DLL, then you do create an instance of the actual DLL itself, because there is no managed platform acting as a virtual machine liason between the program and the operating system. Therefore, the library is handled immediatley by the OS without a managed platform/virtual machine (and classes) acting as an intermediary.
You are mixing loading of the library and the data state here. First of Java does not know libraries (at least not in this sense) and if it uses precompiled libraries though JNI or such it uses the same mechanisms as any C or Pascal program would. And for .NET libraries the same holds true as for a library written in C or Pascal: if the program loads a library the operating system maps the library into the applications virtual memory and then it can call there as it sees fit. No data state is shared between different “instances” by default (while the code is shared).
So assume you have the following code:
library Test;
{$mode objfpc}
var
i: LongInt = 0;
function GetValue: LongInt; stdcall;
begin
if i = 0 then begin
Randomize;
i := Random(High(LongInt) - 1) + 1;
end;
Result := i;
end;
exports
GetValue;
begin
end.
Then you'll get a different number when calling
GetValue for each run of the program no matter if your program is written in Java, C#, Free Pascal or whatever.
Also an important point that I had already mentioned earlier: You do
not pass classes or other Pascal types like
AnsiString or such across library boundaries. This will only lead to problems rather sooner than later. The only safe ones are primitive types, records, pointers (though these need to be freed by whoever allocated them or you need to pass the memory manager along as well) and interfaces (especially the COM ones where designed for this). On Windows you can also pass
WideString, because it uses operating system functionality.
Passing classes and such around will only work once dynamic packages are supported, but these are not ready for prime time yet.