It is not a reply, rather to broaden the question into "calling generic functions from any dll in F#".

I heard this .NetLink from Mathematica that enables Mathematica to call .Net and .Net call "unmanaged" functions reside in a traditional dll.

Since F# has the native .Net capability, how is it possible to do the same thing in its scripting environment?

Thanks,
Hu Zhe

P.S.
link to this Mathematica capability
[link:documents.wolfram.com]

By on 8/1/2006 12:50 PM ()

Hi Chris,

I did a quick search through the F# sources and i found file "ilread.ml" (in the absil directory) where DllImport is used, so you may want to check it out. You have to declare function with type annotatins and you have to pass something as a body (in ilread.ml it is usually failwith "") so I guess it could look like this:

[<DllImport("kernel32.dll")>]
let FillConsoleOutputCharacter ((hConsoleHandle:nativeint),
(cCharacter:byte),
(nLength:int),
(dwWriteCoord:COORD),
(lpNumberOfCharsWritten:???) : bool = failwith "";

However, I didn't try it and I'm not sure what type you should use for "lpNumberOfCharsWritten"...

By on 7/15/2006 9:00 AM ()

Hi, it is probably more difficult than I expected.
I'm not sure whether it is possible to declare pointer to int in F# and the second problem is that if you declare structure COORD, it will be class and not a value type (which I think is required for interop). You may try using Marshal class:

open System
open System.IO
open System.Runtime.InteropServices;;

[<DllImport("kernel32.dll")>]
let FillConsoleOutputCharacter ((hConsoleHandle:nativeint), (cCharacter:byte), (nLength:int),(dwWriteCoord:nativeint), (lpNumberOfCharsWritten:nativeint)) : bool = failwith "";

do
let coord = System.Runtime.InteropServices.Marshal.AllocHGlobal(4) in
let ret = System.Runtime.InteropServices.Marshal.AllocHGlobal(4) in // assumes 32bit integer
let coordArr = ([| 1; 2; |]:int16 array) in
System.Runtime.InteropServices.Marshal.Copy(coordArr,coord,0,4);
let b = FillConsoleOutputCharacter(handle,100,1,coord,ret) in
let r = System.Runtime.InteropServices.Marshal.Copy(ret,retArr,0,4);
..

But I'm really not sure if this can work :-S (I don't know how to get handle for console, so I can't try it).

By on 7/15/2006 10:22 AM ()

I believe the following will work, though I have not tested it (I'm assuming you have a hConsoleHandle).

COORD should really be defined as a struct - here I am assuming that it gets represented as a 32-bit integer in the native calling convention (actually you can tell that is correct by "dw" in the "dwWriteCoord" annotation).

The "&&" prefix operator takes a pointer to a mutable location, generating a value of type "int32 nativeptr". It is only for use in this kind of situation and you will get a warning when you use it. You can also give the pointer a "int byref" type and pass a value of type "int ref" - F# will automatically take the address to the heap-allocated mutable reference value and the CLR interop layer will pin it for the duration of the call.

F# does not yet support struct definitions though we plan to add that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 

open System
open System.IO
open System.Runtime.InteropServices;;

type COORD = int32
let int16_to_int32 (x:int16) = System.Convert.ToInt32(x)
let mk_COORD(x,y) = (int16_to_int32 x) &&& (int16_to_int32 y <<< 16)
[<DllImport("kernel32.dll")>]
let FillConsoleOutputCharacter 
      ((hConsoleHandle:nativeint), 
       (cCharacter:byte), 
       (nLength:int32),
       (dwWriteCoord:COORD),
       (lpNumberOfCharsWritten: int32 nativeptr)) : bool = failwith "";;
let res = 
  let mutable nchars = 0 in 
  FillConsoleOutputCharacter(hConsoleHandle,1uy,1,mk_COORD(10s,11s),&&nchars)

By on 7/17/2006 3:47 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper