使用UnmanagedExports 这真的很简单。
您从功能接口开始,如下所示:
type
IManagedInterface = interface
['{9F5A2431-5559-410C-BAB4-5144CA8C0B7B}']
function CheckCredentials(AContextName, AContainerName, AUserName,
APassword: WideString): integer; safecall;
end;
这可能不是参数类型的最佳选择,因为您不能使用NULL 作为用户名和密码来调用它,而且您可能还想传递其他参数(如上下文类型),但是您明白了。
然后您在 VS 2019 中创建一个新的类库 (.NET Framework) 项目,将构建目标设置为 x86(使其与 Delphi 5 兼容)。为 UnmanagedExports 添加 NuGet 包。
在该项目中添加相同的界面:
[ComVisible(true)]
[Guid("9F5A2431-5559-410C-BAB4-5144CA8C0B7B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IManagedInterface
{
int CheckCredentials(
[MarshalAs(UnmanagedType.BStr)] string contextname,
[MarshalAs(UnmanagedType.BStr)] string container,
[MarshalAs(UnmanagedType.BStr)] string username,
[MarshalAs(UnmanagedType.BStr)] string password);
}
以及实现该接口的类:
public class Class1 : IManagedInterface
{
public int CheckCredentials(string contextname, string container,
string username, string password)
{
var pc = new PrincipalContext(ContextType.Domain, contextname, container);
return Convert.ToInt32(pc.ValidateCredentials(username, password,
ContextOptions.Negotiate));
}
}
最后,您从 DLL 中导出一个函数,该函数创建并返回该类的一个实例:
static class Exports
{
[DllExport]
public static void CreateTheInterface(
[MarshalAs(UnmanagedType.Interface)] out IManagedInterface instance)
{
instance = new Class1();
}
}
现在您可以使用 Delphi 的 DLL(为了保持简短,库不会按需加载,我会在生产代码中这样做):
procedure CreateTheInterface(out AInstance: IManagedInterface); stdcall;
external 'ClassLibrary1.dll';
var
Imi: IManagedInterface;
context, container, username, password: string;
begin
CreateTheInterface(Imi);
if Imi <> nil then try
context := 'testnet.testad.org:636';
container := 'dc=testnet,dc=testad,dc=org';
username := 'someguy';
password := 'password';
Writeln('call returned: ',
Imi.CheckCredentials(context, container, username, password));
except
on E: Exception do
Writeln(E.Message);
end;
Readln;
end.
所以,没有“陷阱”的雷区,这真的很容易。