Torial
SFAICT theres not very much stopping this from working in cobra
Heres cobra code for a simple Pinvoke declaration and invocation.
You need specify both of
shared and
extern and have 'pass' as the body
use System.Runtime.InteropServices
class PInvokeTst
#PInvoke entry point
def messageBeep(beepType as uint32) as bool is shared, extern
has DllImport("User32.dll", setLastError = true)
pass
# PInvoke entry point
def beep(dur as uint32, freg as uint32) as bool is shared, extern
has DllImport("kernel32.dll", setLastError = true)
pass
def main is shared
print .messageBeep(0)
print .messageBeep(16)
print .beep(750, 300)
It doesnt compile because of a check for return types thats not cogniscent of extern on Members. ( i.e wot chuck said)
pinvoke.cobra(5): error: Missing return statement for method "messageBeep" which returns bool.
pinvoke.cobra(9): error: Missing return statement for method "beep" which returns bool.
Compilation failed - 2 errors, 0 warnings
If you get past that,
It fails in the C# compilation phase cos the cobra code gen is adding an empty block to the extern defn (basically same issue as previously expressed in a different place).
c:\home\hops\src\cobra\Tst\regexp\pinvoke.cobra(6): error: "PInvokeTst.MessageBeep(uint)" cannot be extern and declare a body (C#)
c:\home\hops\src\cobra\Tst\regexp\pinvoke.cobra(10): error: "PInvokeTst.Beep(uint, uint)" cannot be extern and declare a body (C#)
Compilation failed - 2 errors, 0 warnings
In spite of 'extern' not being implemented for this exact purpose it does find its way through to the generated C# code and does the desired thing.
Heres the patches to the compiler that allow this to compile.
- Code: Select all
Index: Source/Members.cobra
===================================================================
--- Source/Members.cobra (revision 2474)
+++ Source/Members.cobra (working copy)
@@ -701,6 +701,9 @@
get statements from _stmts
+ get isExtern as bool
+ return 'extern' in _isNames
+
def findLocal(name as String) as AbstractLocalVar?
# TODO: should this use a dictionary lookup?
for local in _locals, if local.name==name, return local
@@ -1204,7 +1207,7 @@
if _implementsTypeNode
_implementsType = _implementsTypeNode.realType
# TODO: make sure the type is among the interfaces of the box
- if .compiler.errors.count==numErrors and _returnType not in [.compiler.voidType to IType, .compiler.passThroughType to IType] and not .hasReturnStmt and not .hasYieldStmt and not .hasThrowStmt and not .isAbstract and not .parentBox.isExtern and not .parentBox inherits Interface
+ if .compiler.errors.count==numErrors and _returnType not in [.compiler.voidType to IType, .compiler.passThroughType to IType] and not .hasReturnStmt and not .hasYieldStmt and not .hasThrowStmt and not .isAbstract and not .parentBox.isExtern and not .parentBox inherits Interface and not .isExtern
.throwError('Missing return statement for method "[_name]" which returns [_returnType.name].')
# check for `return` and `yield` in the same method
if .resultType is not .compiler.voidType
Index: Source/BackEndClr/SharpGenerator.cobra
===================================================================
--- Source/BackEndClr/SharpGenerator.cobra (revision 2474)
+++ Source/BackEndClr/SharpGenerator.cobra (working copy)
@@ -1572,6 +1572,9 @@
pass
def writeSharpImp(sw as CurlyWriter, skipFirst as bool)
+ if .isExtern
+ sw.write(';\n')
+ return
.compiler.codeMemberStack.push(this)
try
sw.writeAndIndent('{\n')
This does not cause any new failures in the existing tests
YMMV with this, Theres possibly additional tweaks needed for some entrypoints (e.g finding the WIN32_FIND_DATA value mentioned above, ...)
and I've not tried anything with explicit out parameters...
Now returning to your regularly scheduled program