我在 win7 和 delphi 2010 上工作。这是我的代码。
library CFGFunc;
uses
sysUtils
Un_ExFuncDll in "base\Un_ExFuncDll.pas"
...
exports
LoadExFuncsInDLL,
...
Un_ExFuncDll.pas 在这里
unit Un_ExFuncDll;
interface
uses
Classes;
procedure LoadexfuncsIndll(); stdcall;
...
编译后,dll 不工作。但是我用
LoadexfuncsIndll()
替换了
LoadExFuncsInDLL()
(与出口中的完全匹配)在Un_ExFuncDll.pas
。然后它起作用了。
Delphi 不区分大小写。但是好像dll里面的exports是case sensitive的。 那么,他们有什么关系呢?
导入/导出 DLL 函数 IS 区分大小写,并且一直如此。该行为与区分大小写的 OS DLL 加载程序相关联。这是 Delphi 语言中仅有的区分大小写的区域之一。这是记录在案的行为,至少部分是:
A name 说明符由指令 name 后跟一个字符串常量组成。如果条目没有 name 说明符,例程将以其原始声明名称 导出,具有相同的拼写和大小写。当您想要以不同的名称导出例程时,请使用 name 子句。
在您的导入声明中,确保与例程名称的拼写和大小写完全匹配。稍后,当您调用导入的例程时,名称不区分大小写。
如果您有数百个导出函数和未知数量的 dll 已为您的应用程序编写,并且您无意中将某些导出例程的名称用驼峰式命名,那么它就是一个真正的 PIA。
这是处理它的一种方法...
procedure GetExportedFunctions(const ModulePath: string; names: TStringList);
function RvaToVa(Module: HMODULE; Rva: Cardinal): Pointer;
begin
Result := Pointer(Rva + Module);
end;
var
Module: HMODULE;
DosHeader: PImageDosHeader;
NtHeaders: PImageNtHeaders;
EntryData: PImageExportDirectory;
POrd: PWord;
p: PDWORD;
i: integer;
begin
names. Clear;
Module := LoadLibraryEx(PChar(ModulePath), 0, LOAD_LIBRARY_AS_DATAFILE);
if Module = 0 then
RaiseLastOSError;
try
DosHeader := PImageDosHeader(Module);
NtHeaders := PImageNtHeaders(NativeUInt(Module) + DosHeader._lfanew);
EntryData := RvaToVa(Module, NtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
if not Assigned(EntryData) then
Exit;
with EntryData^ do begin
POrd := RvaToVa(Module, AddressOfNameOrdinals);
p := RvaToVa(Module, AddressOfNames);
end;
{ Function names }
for i := 0 to EntryData^.NumberOfNames - 1 do begin
names. Add(string(PAnsiChar(RvaToVa(Module, p^))));
Inc(p);
Inc(POrd);
end;
finally
FreeLibrary(Module);
end;
end; { GetExportedFunctions }
function GPA_CaseInsensitive(Module: HMODULE; const ProcName: string): Pointer;
var
EnumNames: TStringList;
i: integer;
FuncName: string;
begin
Result := nil;
EnumNames := TStringList.Create;
try
GetExportedFunctions(GetModuleName(Module), EnumNames);
for i := 0 to EnumNames.count - 1 do begin
FuncName := EnumNames[i];
if SameText(FuncName, ProcName) then begin
Result := GetProcAddress(Module, PChar(FuncName));
Break;
end;
end;
if not Assigned(Result) then begin
MessageBox(0, PChar(Format('Function %s not found in module', [ProcName])),
'DLL Error', MB_SYSTEMMODAL or MB_SETFOREGROUND or MB_TOPMOST or MB_ICONHAND);
end;
finally
EnumNames.Free;
end;
end; { GPA_CaseInsensitive }