Does anyone have some basic advice on how to export a struct from a dll. I know how to do this in C+= but am having trouble in masm. I have done many searches on Google but cannot find useful information on the required steps to follow. Can a struct be exported from a dll? Is the use of a def file necessary if the struct can be exported?
devilhorse,
Its usually the case that if you want a structure full of data from and external function you must pass an empty structure to it so it can fill it with the data you require. I have seen functions designed where the data comes back to you as dynamic memory allocated in the external function but its slow in comparison to passing the structure first.
The attachment is a working example. In the DEF file there may be some way to use DATA instead of the obsolete CONSTANT, but in the time I had to spend on it I could not find any way.
Importing into an Application (http://msdn.microsoft.com/en-us/library/kh1zw7z7(v=VS.80).aspx)
Thank You for your fast reply.
Here is another example showing two alternative methods: Use a global structure inside the DLL (A), or pass a pointer to a structure to the DLL (B).
The DLL:
include \masm32\include\masm32rt.inc
.data?
TheRect RECT <?> ; we use a global structure in the DLL for method B
.code
LibMain proc instance:DWORD, reason:DWORD, unused:DWORD
mov eax, TRUE
ret
LibMain endp
GetTheRectA proc pStruct ; $export
invoke GetClientRect, rv(GetDesktopWindow), pStruct
mov eax, pStruct
ret
GetTheRectA endp
GetTheRectB proc ; $export
mov eax, offset TheRect
push eax
push eax
push rv(GetDesktopWindow)
call GetClientRect
pop eax ; aka offset TheRect
ret
GetTheRectB endp
end LibMain
The calling code:
include \masm32\include\masm32rt.inc
.data?
hDll dd ?
rectCaller RECT <?>
pUseA dd ?
pUseB dd ?
.code
start:
mov hDll, rv(LoadLibrary, chr$("Struct_Dll")) ; rv is the retval macro ([url=\masm32\macros\macros.asm#"rv macro"]source[/url]), which returns eax
.if eax
mov pUseA, rv(GetProcAddress, hDll, chr$("GetTheRectA"))
.if eax
push offset rectCaller ; we use a global structure for method A
call pUseA
xchg ebx, eax ; move the pointer to the structure into a protected register
print "Desktop width and height, method A: "
print str$([ebx.RECT.right]), "/"
print str$([ebx.RECT.bottom]), 13, 10
.else
invoke MessageBox, 0, chr$("GetTheRectA not found"), 0, MB_OK
.endif
mov pUseB, rv(GetProcAddress, hDll, chr$("GetTheRectB"))
.if eax
call pUseB
print "Desktop width and height, method B: "
print str$([rectCaller.right]), "/"
print str$([rectCaller.bottom])
.else
invoke MessageBox, 0, chr$("GetTheRectB not found"), 0, MB_OK
.endif
invoke FreeLibrary, hDll
.else
invoke MessageBox, 0, chr$("DLL not found"), 0, MB_OK
.endif
exit
end start