I can't remember if this has come up, couldn't find any references in any of the docs or forum threads.
Is P/Invoke supported w/ Cobra? If so, what is the syntax?
Thanks! (And Happy New Year!)
Forums
P/Invoke
24 posts
• Page 1 of 3 • 1, 2, 3
Re: P/Invoke
You can find the syntax for attributes in the test cases at:
http://cobra-language.com/trac/cobra/browser/cobra/trunk/Tests/320-misc-two/800-attributes
http://cobra-language.com/trac/cobra/browser/cobra/trunk/Tests/320-misc-two/800-attributes
- Charles
- Posts: 2515
- Location: Los Angeles, CA
Re: P/Invoke
I'm not seeing anything that relates to P/Invoke. Is there a particular attribute you are thinking of that allows for P/Invoke calls?
- torial
- Posts: 229
- Location: IA
Re: P/Invoke
Maybe I don't realize what you're trying to do. When I search for "C# P/Invoke" I hit this page which uses a DllImport attribute:
http://msdn.microsoft.com/en-us/magazine/cc164123.aspx
This page uses the same attribute:
http://www.codeproject.com/KB/cs/essentialpinvoke.aspx
Is there something else you want to do? If so, please provide an example or more specifics.
http://msdn.microsoft.com/en-us/magazine/cc164123.aspx
This page uses the same attribute:
http://www.codeproject.com/KB/cs/essentialpinvoke.aspx
Is there something else you want to do? If so, please provide an example or more specifics.
- Charles
- Posts: 2515
- Location: Los Angeles, CA
Re: P/Invoke
Yeah, the DLLImport attribute is part of it. I was thinking of the "extern" keyword used in C#. Is anything like that required for making the p/invoke call work?
Here's a sample P/Invoke (http://www.pinvoke.net/default.aspx/ker ... ndNextFile)
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA
lpFindFileData);
Would the conversion be:
I see a reference to an "extern" keyword, but it seems to be for a replacement of "fake" which doesn't seem for this purpose: http://cobra-language.com/trac/cobra/changeset/1654
Here's a sample P/Invoke (http://www.pinvoke.net/default.aspx/ker ... ndNextFile)
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA
lpFindFileData);
Would the conversion be:
def FindNextFile(hFindFile as IntPtr, lpFindFileData as out WIN32_FIND_DATA) as bool is shared
has DLLImport("kernel32.dll", charSet=CharSet.Auto)
I see a reference to an "extern" keyword, but it seems to be for a replacement of "fake" which doesn't seem for this purpose: http://cobra-language.com/trac/cobra/changeset/1654
- torial
- Posts: 229
- Location: IA
Re: P/Invoke
The conversion looks good to me except that (a) I'm not familiar with WIN32_FIND_DATA and (b) I just realized these are bodiless methods in C# obviously since they are external--Cobra does not currently support that. Doh!
The "extern" is so that if you include a C# class like so:
You can tell the Cobra compiler what the C# class looks like. It's a rarely used feature since typically C# code would just get compiled to a DLL that you would use.
So you have 2 options today:
1)
Do your P/Invoke work in C# and compile to a DLL when your Cobra code @ref's.
2)
Do your P/Invoke work in C# and pass the file to the Cobra compiler, with a mirror "is extern" declaration somewhere in the Cobra source code.
I would lean towards (1).
Also, I've be able to avoid P/Invoke most of the time because I find someone has already made a wrapper, or provided some kind of library with equivalent functionality either in the .NET standard libs, or 3rd party [open source].
HTH
The "extern" is so that if you include a C# class like so:
- Code: Select all
cobra -c -d Foo.cobra Bar.cs
You can tell the Cobra compiler what the C# class looks like. It's a rarely used feature since typically C# code would just get compiled to a DLL that you would use.
So you have 2 options today:
1)
Do your P/Invoke work in C# and compile to a DLL when your Cobra code @ref's.
2)
Do your P/Invoke work in C# and pass the file to the Cobra compiler, with a mirror "is extern" declaration somewhere in the Cobra source code.
I would lean towards (1).
Also, I've be able to avoid P/Invoke most of the time because I find someone has already made a wrapper, or provided some kind of library with equivalent functionality either in the .NET standard libs, or 3rd party [open source].
HTH
- Charles
- Posts: 2515
- Location: Los Angeles, CA
Re: P/Invoke
Is there a way I could trick it using the "sharp" keyword, like:
sharp"extern" def fxnName(a as B, c as D) ?
I've been doing a hobby project over New Year's vacation, and tried to keep as much in Cobra as possible (even ported a Boyer-Moore class from C# to Cobra).
Or perhaps even do the full <DLLImport....> static extern ... , within the sharp"..." syntax? I haven't played with it so don't know how flexible it is.
sharp"extern" def fxnName(a as B, c as D) ?
I've been doing a hobby project over New Year's vacation, and tried to keep as much in Cobra as possible (even ported a Boyer-Moore class from C# to Cobra).
Or perhaps even do the full <DLLImport....> static extern ... , within the sharp"..." syntax? I haven't played with it so don't know how flexible it is.
- torial
- Posts: 229
- Location: IA
Re: P/Invoke
Sorry, sharp'foo' only works where expressions and statements are expected.
Btw what native libs are you calling out to?
Btw what native libs are you calling out to?
- Charles
- Posts: 2515
- Location: Los Angeles, CA
Re: P/Invoke
I've got two problems I wish to solve using the P/Invoke strategy:
a) Get a Windows Shell Context Menu options ( as described at http://www.codeproject.com/KB/cs/shellContextMenu.aspx ). In particular, I wish to right click on a file and show the same (or close to the same) context menu that someone using Windows Explorer would see.
b) Find a faster way to scan through directories (research on the internet indicates that P/Invoke is about 10x faster than Directory.GetFiles and the folder equivalent): http://stackoverflow.com/questions/7241 ... ely-in-net. For b) I also have a command switch option I'll experiment w/ for performance.
I've attached a screesnhot of what I've got so far...
a) Get a Windows Shell Context Menu options ( as described at http://www.codeproject.com/KB/cs/shellContextMenu.aspx ). In particular, I wish to right click on a file and show the same (or close to the same) context menu that someone using Windows Explorer would see.
b) Find a faster way to scan through directories (research on the internet indicates that P/Invoke is about 10x faster than Directory.GetFiles and the folder equivalent): http://stackoverflow.com/questions/7241 ... ely-in-net. For b) I also have a command switch option I'll experiment w/ for performance.
I've attached a screesnhot of what I've got so far...
- Attachments
-
- File Search sample
- fileSearcher.jpg (148.98 KiB) Viewed 21936 times
- torial
- Posts: 229
- Location: IA
Re: P/Invoke
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
It doesnt compile because of a check for return types thats not cogniscent of extern on Members. ( i.e wot chuck said)
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).
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.
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
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
- hopscc
- Posts: 632
- Location: New Plymouth, Taranaki, New Zealand
24 posts
• Page 1 of 3 • 1, 2, 3
Who is online
Users browsing this forum: No registered users and 29 guests