[Solved] NG LoadLibraryA/GetProc conflicting types

BlitzMax Forums/BlitzMax NG/[Solved] NG LoadLibraryA/GetProc conflicting types

RustyKristi(Posted 2016) [#1]
It seems the external DLL library loading is also a problem

 error: conflicting types for 'LoadLibraryA'
 extern BBINT __stdcall  LoadLibraryA(BBBYTE * bbt_dll);

note: previous declaration of 'LoadLibraryA' was here
   WINBASEAPI HMODULE WINAPI LoadLibraryA (LPCSTR lpLibFileName);


error: conflicting types for 'GetProcAddress'
 extern BBBYTE* __stdcall  GetProcAddress(BBINT bbt_libhandle,BBBYTE * bbt_func);

note: previous declaration of 'GetProcAddress' was here
   WINBASEAPI FARPROC WINAPI GetProcAddress (HMODULE hModule, LPCSTR lpProcName);




Anybody got a solution?


col(Posted 2016) [#2]
Hiya,

Are you defining it yourself? If so there's no need to as it's been defined but I can't remember where :p

The problem comes because legacy 'max used integers (32bit) to represent byte pointers, which is ok on a 32bit system, but ng supports 64bit too so the return value needs to fit in a 64bit variable. Therefore the return value for LoadLibraryA/W is changed to a Byte Ptr. A Byte Ptr will resolve to a 32 or 64 bit byte pointer automatically depending on the build option :p

Local lib:Byte Ptr = LoadLibraryA("mydll.dll")

works here without a probrlem.

Hope it helps


col(Posted 2016) [#3]
Ahh, I just took more notice of your post here and some previous post regarding cleaning modules.

It looks as though you may have removed the .x file that it used to prevent the confliction? It will be in the modules folder ( which, after looking, should be in \pub.mod\win32.mod. There should be several .x files in there.


RustyKristi(Posted 2016) [#4]
Hey col, thanks. No I'm just trying to use a simple DLL to test with NG. Obviously this works in vanilla but again it's been tricky with NG.

I have not removed any files, about 8 .x files are still there.


RustyKristi(Posted 2016) [#5]
Yes and also sorry if it might confuse you with the cleaning modules that I have asked in another thread, it is totally unrelated to this issue apparently.


RustyKristi(Posted 2016) [#6]
Ok so I set my lib to byte ptr..

Global lib:Byte Ptr 


now I'm getting 'Unable to convert from Byte Ptr to Int.' at this part..

	Function GetProcWin32@ Ptr( proc$ )
		Local p@ Ptr
		p = GetProcAddress( lib, proc ) <--- ERROR HERE
		If ( p ) Return p
		Print "Error" + proc
		End
	EndFunction



Henri(Posted 2016) [#7]
Hi,

this seems to work:
Strict

Global lib:Byte Ptr = LoadLibraryA("user32")

If Not lib
	DebugLog "LoadLibrary failed !"
Else
	DebugLog "OK!"
EndIf

Local func:Byte Ptr = GetProcWin32("CopyIcon")

Function GetProcWin32:Byte Ptr( proc:String )	
	Local p:Byte Ptr = GetProcAddress( lib, proc )
	If Not p Then Print "Error: " + proc; End
	
	Return p
EndFunction


-Henri


RustyKristi(Posted 2016) [#8]
thanks Henri,

Sorry for not completing, but this is how my function is setup:

Type DLL
        
        Global lib 

  	Function OpenDLL( path$  )
		DLL.lib = LoadLibraryA( path )
        End Function
   
        DLL.LibFunction1 = DLL.GetProcWin32("function1")
        DLL.LibFunction2 = DLL.GetProcWin32("function2")
        ...

        Function GetProcWin32( proc$ )	
	  p = GetProcAddress( DLL.lib, proc )
        End Function

End Type


On top of that, it has these Externs:

Extern "win32"
	Function LoadLibraryA( dll$z )
	Function GetProcAddress( libhandle%, func$z )
EndExtern


I thought it's gonna resolve on the part..

Also not sure what does the "z" stand at the end of that string (string pointer?) but apparently it works on vanilla and it's my first time seeing that.


xlsior(Posted 2016) [#9]
IIRC $z is a null-terminated C-tyle string


Henri(Posted 2016) [#10]
As xlsior said, when you are passing a Blitz-string to an external function the string is converted to array of bytes with a null terminator. If this reserved memory is not freed the a small memory leak is introduced. The 'z' after string definition will internally call memfree to free the reserved memory. Otherwise you have to do it yourself.

Your problem is in
Function GetProcAddress( libhandle%, func$z )
where libhandle is defined as int (%) when it should be byte ptr. Or if you comment out all the Externs it should work. Also it would make debugging easier if 'Strict' is used.

-Henri


RustyKristi(Posted 2016) [#11]
Yes, I'm using Strict and when I comment out the Externs, I'm now getting Identifier 'loadlibrarya' not found.

I'm building a module that loads a DLL library if that makes any difference..


RustyKristi(Posted 2016) [#12]
Hey, finally thanks a lot guys. That did it!!!

What I did..

Remove Externs as you suggested Henri, thanks!

Set lib variable to Byte Ptr (by col, thanx!)

and this will search for LoadLibraryA so I import Pub.Win32 which I assume has the conflicting LoadLibraryA extern in the first place (did a search) :-)

Now it builds and links apps perfectly :D!


BTW. what is the equivalent of variablename ptr ptr in NG?? I just removed the ptr ptr and so far it runs ok (I hope)


RustyKristi(Posted 2016) [#13]
Hey, finally thanks a lot guys. That did it!!!

What I did..

Remove Externs as you suggested Henri, thanks!

Set lib variable to Byte Ptr (by col)

and this will search for LoadLibraryA so I import Pub.Win32 which I assume has the conflicting LoadLibraryA extern in the first place (did a search) :-)

Now it builds and links apps perfectly :D!


BTW. what is the equivalent of variablename ptr ptr in NG?? I just removed the ptr ptr and so far it runs ok (I hope)

Edit: just removed the extra ptr, I forgot I already asked this on another thread..
variablename ptr -> OK


col(Posted 2016) [#14]
Yes, when calling functions that go to the OS ( or c/c++ code ) then its always good to know the true parameter and return types that the function is expecting. If it expects or returns a pointer other than the usual short,int,float,double then you will probably need a Byte Ptr.
Strings are slightly different in that you can use $z to auto convert to a char* or $w to auto convert to a short* or wchar_t* etc, or alternatively use a Byte Ptr for a char* and Short Ptr for a short*/wchar_t*.
Experience will help get to know which one to use just by looking at the c/c++ function protoype.

NG is more accurate with using the correct datatype than legacy max is due to the nature of requiring 64bit pointers for a 64bit build.

Your confliction actually came from you redefining the function incorrectly ;-) If the function wasn't defined ( as it wasn't until you imported pub.win32 ) and you get a confliction then you could create a .x file yourself, in the same folder as the file that has the conflicting function, and put the function protoype/defintion inside it, this would then be used to resolve the conflict automatically.

Also be aware than if you use SuperStrict then functions with no return type will return void on the C side of things ( NG compiles your 'Max code to C then compiles that C code with GCC to build your exe ), however if you use Strict then all parameters/return values will default to an integer. It caught me a few times at first. :D


RustyKristi(Posted 2016) [#15]
Thanks for the additional info Dave. Yes, clearly this was a blitzmax newbie mistake from me as I just really want to go with the .x file method but apparently I don't know how to do those conversions, do you?

I would like to know how those X redefinition fix works. :-)


col(Posted 2016) [#16]
I don't know its capabilities other than allowing you to define a function that ends with ! ( the C 'not' operator ) and bcc will 'not' output a function definition for it, thereby the C code will use the original one defined in a header file somewhere. I could be totally wrong here and Brucey is the best one to give a better explanation of it, and also to explain if it could be used for anything else.

I'd also imagine that it has something to do with the gazillion different datatypes that the Win32API uses. And at the end of the day all of those datatypes resolve down to the regular C standard types which NG outputs to - thereby making everything compatible.

All I know is that you can put the offending function in it with its proper C parameter types, stick a ! on the end and then things compile and work :D

Sorry I couldn't explain any deeper and Brucey is the one to answer the question more accurately - I'm probably miles off :D


RustyKristi(Posted 2016) [#17]
Thanks and no worries Dave! Those info really helped me get a better understanding with some adjustments to NG and how they work. :D appreciate it, cheers.