Undefined reference to '{function_name}'

Started by chalky, June 11, 2024, 16:33:58

Previous topic - Next topic

chalky

The following:

Extern "win32"
    Function CopyMemory:Long(hpvDest:String,hpvSource:String,cbCopy:Long)
End Extern

fails with:

undefined reference to 'CopyMemory@16'
during compilation. Similarly, the following:

Extern "win32"
    Function ClosePrinter:Long(hPrinter:Long)
    Function IsBadStringPtrByLong:Long(lpsz:Long,ucchMax:Long)
    Function OpenPrinter:Long(pPrinterName:String,phPrinter:Long,pDefault:TPrinterDefaults)
    Function GetPrinterApi:Long(hPrinter:Long,Level:Long,Buffer:Long,pbSize:Long,pbSizeNeeded:Long)
End Extern

all fail too with:

undefined reference to 'ClosePrinter@8'
undefined reference to 'IsBadStringPtrByLong@40'
undefined reference to 'OpenPrinter@16'
undefined reference to 'GetPrinterApi@40'

I remember having this issue several years ago, but cannot remember how/if I ever got round it.  Can anyone help me with what I need to do to get it to work?

dawlane

The compiler has failed to link against whatever library or share library you are trying to link against.
Options:
Make sure that the library name is in compiler/linker command line options.
Make sure that the library is is correct, and exports those functions.
Make sure that the library is in the compiler/linker's search path.
Make sure that the linking order for all libraries are correct. Some libraries require that it's dependencies are linked to the application first. 

chalky

Thank you dawlane.

I have modified my code to manually load/check the function(s). However, I have clearly done something wrong, as [for example] the following compiles fine but fails to work:

SuperStrict

Type TDevMode
    Field dmDeviceName:String
    Field dmSpecVersion:Int
    Field dmDriverVersion:Int
    Field dmSize:Int
    Field dmDriverExtra:Int
    Field dmFields:Long
    Field dmOrientation:Int
    Field dmPaperSize:Int
    Field dmPaperLength:Int
    Field dmPaperWidth:Int
    Field dmScale:Int
    Field dmCopies:Int
    Field dmDefaultSource:Int
    Field dmPrintQuality:Int
    Field dmColor:Int
    Field dmDuplex:Int
    Field dmYResolution:Int
    Field dmTTOption:Int
    Field dmCollate:Int
    Field dmFormName:String
    Field dmLogPixels:Int
    Field dmBitsPerPel:Long
    Field dmPelsWidth:Long
    Field dmPelsHeight:Long
    Field dmDisplayFlags:Long
    Field dmDisplayFrequency:Long
EndType

Type TPrinterDefaults
    Field pDatatype:String
    Field pDevMode:TDevMode=New TDevMode
    Field DesiredAccess:Long
EndType

Local OpenPrinter:Long(pPrinterName:String,phPrinter:Long Var,pDefault:TPrinterDefaults) "win32"
Local winspool:Long=LoadLibraryA("winspool.drv")

If winspool Then
   OpenPrinter=GetProcAddress(winspool,"OpenPrinterA")
   If Not OpenPrinter Then
       Print "Library error!"
       End
   EndIf
EndIf

Local pDef:TPrinterDefaults=New TPrinterDefaults
Local pHnd:Long
Local rVal:Long

pDef.DesiredAccess=8

rVal=OpenPrinter("CutePDF Writer",pHnd,pDef)
Print rVal
Print pHnd

as rVal always equals 0, indicating the call has failed.

Any guidance on what I've done wrong would be much appreciated.

dawlane

Quote from: chalky on June 12, 2024, 13:40:27Local OpenPrinter:Long(pPrinterName:String,phPrinter:Long Var,pDefault:TPrinterDefaults) "win32"
Guess this is the problem.

Has it been declared as Extern?
Are the parameter types correct?
Is the return type an actual long type or a pointer to the function?
Should it use the Local keyword?

Quote from: chalky on June 12, 2024, 13:40:27OpenPrinter=GetProcAddress(winspool,"OpenPrinterA")
Then there's this. Which would clash with the former.

Read everything in the advanced topics.
https://blitzmax.org/docs/en/language/interfacing_with_c/
https://blitzmax.org/docs/en/language/pointers/


chalky

Thanks again dawlane.

I tried running the code Henri posted in the blitzcoder thread you linked to, but it refuses to compile due to an "Unable to convert from 'Int' to 'Byte Ptr'" error:

Strict

Global lib:Byte Ptr = LoadLibraryA("user32")  <-- Unable to convert from 'Int' to 'Byte Ptr'

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

The thread on that site refers to NG whereas I am trying to get this to work on vanilla BlitzMax - is that why I cannot get it to compile?

Sorry - I clearly have a lot to learn here...

chalky

Doesn't matter - I have taken a different approach which no longer requires any external function definitions...