so what is it with these library project? if packages are the way to create new .net assemblies, why were library project kept in delphi 8 for .net as viable targets? the answer can be found in a unique way of offering win32 interoperability. several people were involved, like brian long, roy nelson and danny thorpe, and in the end a special feature of the .net loader was added to delphi 8 for .net library projects. the ability to have a .net assembly that can be loaded by a .net application but also by an unmanaged win32 application. and i'm not talking about a single source project, but about a single binary project. the same binary, available to be used from .net as well as unmanaged win32.
the only special thing that's required, is that the .net assembly has to be marked as unsafe. as an example of this feature, consider the following delphi 8 for .net library, which is marked with the {$unsafecode on} compiler directive to produce unsafe code.
library hashpassword;
{%delphidotnetassemblycompiler '$(systemroot)\microsoft.net\framework\v1.1.4322\system.web.dll'}
{%delphidotnetassemblycompiler 'c:\program files\common files\borland shared\bds\shared assemblies\2.0\borland.delphi.dll'}
{$unsafecode on}
uses
system.web.security;
function hashpasswordmd5(const passwd: string): string;
begin
result := formsauthentication.
hashpasswordforstoringinconfigfile(passwd, 'md5')
end;
function hashpasswordsha1(const passwd: string): string;
begin
result := formsauthentication.
hashpasswordforstoringinconfigfile(passwd, 'sha1')
end;
exports
hashpasswordmd5,
hashpasswordsha1;
end.
the resulting (unsafe) assembly can be used from both .net applications and win32 applications.
calling from .net
to call the assembly from a .net application, we have to add it as a reference to the .net project, add the hashpassword unit to the uses clause, and just use it as any other .net assembly. the only difference is that this particular assembly has been marked with the {$unsafecode on} compiler directive, so our save, managed .net executable is using an unsafe assembly. the executable itself is safe, but the assembly that it uses is not.
implementation
uses
hashpassword;
...
procedure twinform.button1_click(sender: system.object; e: system.eventargs);
begin
messagebox.show('md5: [' +
hashpassword.unit.hashpasswordmd5(textbox1.text) + ']');
messagebox.show('sha1: [' +
hashpassword.unit.hashpasswordsha1(textbox1.text) + ']');
end;
note the unit part of the hashpassword.unit.hashpasswordmd5 and hashpassword.unit.hashpasswordsha1 methods calls. this is due to the fact that the .net platform does not support the notion of a stand-alone global procedure. all procedures and functions must be members of a class type.
danny thorpe explained that rather than reject all delphi source code that contains global procedure definitions (not a popular choice), borland decided to implemented global procedures and functions as members of a compiler-generated class called "unit". the same goes for global variables - they have to live somewhere. our delphi source code never needs to know about those implementation details - the delphi compiler translates our calls to these global routines into the implementation specifics automatically.
the end result is that delphi 8 for .net supports existing source code that declares global procedures, but only delphi code will have transparent access to these non-.net style things. these procedures and functions can be called by c# if the c# programmer works at it, but it will not feel as natural as in delphi because c# doesn't have the concept of a global procedure with no class type.
note that implementation details such as how the delphi compiler represents global procedures and other non-.net concepts are subject to change between major releases. global procedures can be placed somewhere else in future versions of delphi!
calling from win32