Interfacing with C / C++

Monkey Forums/Monkey Bug Reports/Interfacing with C / C++

Pharmhaus(Posted 2015) [#1]
Hi mark,

I am sorry for the inconvenience. This is not a bug but it would be nice of you if you could add some #defines to the monkey core so that interfacing with C and C++ based libaries is a lot easier. Since it is possible to link to libaries with GCC directly it would be great if the conversion to C and Uft8 formatted strings could be implemented as native "functions" in monkey. Here is a simple MessageBox example using user32.dll :

apiTest.cpp
#define ToCString(_1) (_1).ToCString<char>()
// To Utf8?
// To Widestring?


apiTest.monkey
#CC_OPTS += "-static -lUser32"

Import "apiTest.cpp"

Extern

	'int WINAPI MessageBox(
	'	_In_opt_  HWND hWnd,
	'	_In_opt_  LPCTSTR lpText,
	'	_In_opt_  LPCTSTR lpCaption,
	'	_In_      UINT uType
	');
	
	Function MessageBox:Int(hwnd:Int, x:CString, y:CString, type:Int) = "MessageBoxA"
	Function ToCString:CString(str:String)
	
	'Fake class to ensure type safety
	Class CString Abstract
	End
	
Public

Function Main:Int()
	MessageBox(0, ToCString("HEllo"), ToCString("World!"), 0)
	Return 0
End


It would also be very kind of you if you could explain how to interface with external c++ code and how to pass / return monkey object properly. Since c++ always requires prototypes and such, I am currently kind of stuck because I do not know how to handle this and other people have been facing the same problem recently(see here or here). Just for the case that there is currently no way to handle these scenarios I kindly ask you to implement a workaround (maybe a {beforetranscode} {after transcode} area where headerfiles / regular files could be injected?, Or the possibility to properly order imports?)



One of the problems that makes interfacing with c++ extremly hard is monkeys dead code elimination because it removes all code that might be still in use by external c++ code. Reflecting everthing might work for very tiny application but for real projects, this causes a lot of headaches and increases compile time too much. I am currently using this dirty hack which introduces a new preprocessor variable called NO_DEADCODE_ELIMINATION were modules which should be excluded from dead code elimination (for what ever reason) can be added. It would be greatly appreciated if you could implement a similiar solution in further versions of monkey.

trans/decl.monkey -> AppDecl

	Method OnSemant()
	
		_env=Null
		
		mainFunc=mainModule.FindFuncDecl( "Main",[] )
		
		If Not mainFunc Err "Function 'Main' not found."
		
		If Not IntType( mainFunc.retType ) Or mainFunc.argDecls.Length
			Err "Main function must be of type Main:Int()"
		Endif
		
		PreventDeadCodeElimination
		FinalizeClasses
	End

	Method PreventDeadCodeElimination()
		Local deadCode:= New StringStack(GetConfigVar("NO_DEADCODE_ELIMINATION").Split(";"))
		Local includedModules:= New StringStack()

		For Local modules:ModuleDecl = EachIn imported.Values

			Local enableModules:Bool = False
			
			For Local i:Int = 0 Until deadCode.Length
				If deadCode.Get(i) = "" Then Continue
				
				If deadCode.Get(i).EndsWith("*") And modules.modpath.StartsWith(deadCode.Get(i)[ .. deadCode.Get(i).Length - 2] + ".") Then
					enableModules = True
					Exit
				ElseIf deadCode.Get(i) = modules.modpath
					enableModules = True
					Exit
				EndIf
			Next
			
			If enableModules Then
				includedModules.Push(modules.rmodpath)
				modules.SemantAll()
			EndIf
		Next
		
		Print ">>>>>>>>> The following modules have been excluded from deadcode elimination"
		For Local i:String = EachIn includedModules
			Print i
		Next
		Print "<<<<<<<<<"
		
	End