Wrapping a DLL import in a module in F# - f#

I'm attempting to create a "wrapper" module for some windows api functions from user32.dll. I'm still learning F# so I'm rather fuzzy on how inheritance and polymorphism works in F# and how to apply that to this situation.
I have this module:
module MouseControl =
[<DllImport( "user32.dll", CallingConvention = CallingConvention.Cdecl )>]
extern void ShowCursor(bool show)
[<DllImport( "user32.dll", CallingConvention = CallingConvention.Cdecl )>]
extern void internal mouse_event(int flags, int dX, int dY, int buttons, int extraInfo)
let MouseEvent(flags, dX, dY, buttons, extraInfo) = mouse_event(flags, dX, dY, buttons, extraInfo)
My goal is to be able to "hide" the mouse_event function from other code that uses this module and instead expose that function as MouseEvent. With this code both mouse_event and MouseEvent are currently available to code that calls this module. How do I hide mouse_event where it's private to the module?

In your code sample, you already marked the mouse_event function as internal - so in principle, you should just need to mark it as private. However, it looks that F# compiler is ignoring visibility annotations on extern members, so the easiest option is to put them in a nested module and hide the whole nested module:
module MouseControl =
module private Imported =
[<DllImport( "user32.dll", CallingConvention = CallingConvention.Cdecl )>]
extern void mouse_event(int flags, int dX, int dY, int buttons, int extraInfo)
let MouseEvent(flags, dX, dY, buttons, extraInfo) =
Imported.mouse_event(flags, dX, dY, buttons, extraInfo)
The module Imported is now visible only inside the MouseControl module. From the outside, you cannot access anything inside MouseControl.Imported.

Related

How can I hide some parameters from C DLL function on JNA Wrapper side?

I've successfully wrapped a C DLL library using JNA.
As I'm not the owner of the C development part, I would like to hide
some parameters of a C function that I've wrapped on java side.
To be more precise my java code is as follows :
public interface IJNALibrary extends Library {
// INIT FUNCTION
public int initFunction(int firstValue, int secondValue, int thirdValue);
}
On the C side I have in the *.h file :
extern "C" CSAMPLE_API int initFunction (
unsigned firstValue,
unsigned secondValue,
unsigned thirdValue);
My purpose is to directly set secondValue and thirdValue parameters to 1 and thus hide those parameters to the java API user.
I don't want the user to know that he could change the values of those parameters.
In fact I would like to have something like :
public interface IJNALibrary extends Library {
// INIT FUNCTION
public int initFunction(int firstValue);
}
and initFunction(int firstValue) calls initFunction(int firstValue, int secondValue, int thirdValue) from the C DLL part.
But this has to be done inside the java Wrapper and not from the code which calls the java Wrapper.
I'm afraid that It cannot be possible, is it?
Unless I create another C DLL (with public int initFunction(int firstValue) function) which calls the first C DLL(which embed initFunction(int firstValue, int secondValue, int thirdValue).But I would rather do it on the java side in order not to have manage 2 C DLLs.
See also below the Sample.java file which calls the mapped method defined in IJNALibrary interface.
public class Sample {
static IJNALibrary IJNAFunctions;
public static void main(String[] args) throws IOException {
System.setProperty("jna.library.path", "./librayPath");
// LOADING LIBRARY
IJNAFunctions = (IJNALibrary) Native.load("c", IJNALibrary.class);
int firstValue = 1;
int secondValue = 2;
int thirdValue = 3;
int initReturn = IJNAFunctions.initFunction(firstValue, secondValue, thirdValue);
}
}
Thanx for your help.
It depends on what you want to archive. If you want to make it easier for users to call the init, this is an option (demonstrated using gethostname from libc), which uses a Java 8 feature, which allows adding default methods to interfaces:
public class TestDefaultMethod {
public static interface LibC extends Library {
LibC INSTANCE = Native.load("c", LibC.class);
// Original binding of method
int gethostname(byte[] name, int len);
// Helper method to make it easier to call gethostname
default String gethostname() {
byte[] result = new byte[255];
LibC.INSTANCE.gethostname(result, result.length);
return Native.toString(result);
}
}
public static void main(String[] args) {
// Usage
System.out.println(LibC.INSTANCE.gethostname());
}
}
Java developers normally don't arrays to functions, which fill them and a java developer would never pass the length of the array in a separate parameter. These are artifacts of the C nature of the function. In the wrapped function an array is allocated, the native call done and the array then unwrapped. All the ugly C specialties are hidden in the default method.
If you don't want to expose the method on java at all (be warned, if your users can access the JNA library, they can circumvent your protections!), you can use a function pointer directly:
public class TestDefaultMethod {
public static interface LibC extends Library {
NativeLibrary libc = NativeLibrary.getInstance("c");
LibC INSTANCE = Native.load("c", LibC.class);
default String gethostname() {
byte[] result = new byte[255];
libc.getFunction("gethostname").invokeInt(new Object[] {result, result.length});
return Native.toString(result);
}
}
public static void main(String[] args) {
System.out.println(LibC.INSTANCE.gethostname());
}
}
Same idea as above, the default method will hide the ugly parts. In this case though the function is not accessed through the managed INSTANCE, but access through the function pointer directly.

Calling a dll created in VB6 from F#

I am trying to call a dll file created in vb6 from F#. I have written the following dll.
Public Function AddTwoNumbers(ByVal a As Integer, ByVal b As Integer)
AddTwoNumbers = a + b
End Function
Now I want to call it in my F# program, I wrote this code
open System.Runtime.InteropServices
module InteropWithNative =
[<DllImport(#"C:\add", CallingConvention = CallingConvention.Cdecl)>]
void AddTwoNumbers(int, int)
InteropWithNative.AddTwoNumbers(3,4)
let result = AddTwoNumbers_ 2.0 3.0
It gives me errors and doesn't recognize the function.
A working interop example with an EntryPoint
open System.Runtime.InteropServices // for DllImport
module KernelInterop =
[<DllImport("kernel32.dll", EntryPoint="Beep")>]
extern void Beep( int frequency, int duration )
KernelInterop.Beep // val Beep : int * int -> unit
KernelInterop.Beep(440, 1000)

Is it possible to access OpenGL ES from RoboVM without using LibGDX?

Is it possible to access OpenGL ES on iOS from RoboVM without using LibGDX? If so, are there any useful references?
The only thing I can find is this super-simple demo from over 2 years ago: http://robovm.com/ios-opengles-in-java-on-robovm/
But it doesn't provide any functions besides glClearColor and glClear.
The Apple GLKit framework seems to be implemented, though. I just can't find all the actual glWhatever(...) functions...
Yes, it is possible. You need two things for this: 1. Access to the OpenGL ES functions (like glClear(...), etc.) and 2. a UIView in your app that can draw the GL image.
Turns out the second point is very easy. You can either use a GLKView (requires iOS 5.0) or a CAEAGLLayer (requires iOS 2.0) if you're feeling nostalgic. For both, there are tons of tutorials online on how to use them in Objective-C, which can readily be translated to RoboVM. So, I won't spend too much time on this point here.
Access to the OpenGL ES functions is a little more difficult, as RoboVM doesn't ship with the definitions file out of the box. So, we'll have to build our own using Bro. Turns out, once you wrap your head around how Bro handles C-strings, variable pointers, IntBuffers and such (which is actually quite beautiful!), it's really pretty straight forward. The super-simple demo I linked to in the original question is the right starting point.
In the interest of brevity, let me post here just a very abridged version of the file I wrote to illustrate the way the different data types can be handled:
import java.nio.Buffer;
import java.nio.IntBuffer;
import org.robovm.rt.bro.Bro;
import org.robovm.rt.bro.Struct;
import org.robovm.rt.bro.annotation.Bridge;
import org.robovm.rt.bro.annotation.Library;
import org.robovm.rt.bro.ptr.BytePtr;
import org.robovm.rt.bro.ptr.BytePtr.BytePtrPtr;
import org.robovm.rt.bro.ptr.IntPtr;
#Library("OpenGLES")
public class GLES20 {
public static final int GL_DEPTH_BUFFER_BIT = 0x00000100;
public static final int GL_STENCIL_BUFFER_BIT = 0x00000400;
public static final int GL_COLOR_BUFFER_BIT = 0x00004000;
public static final int GL_FALSE = 0;
public static final int GL_TRUE = 1;
private static final int MAX_INFO_LOG_LENGTH = 10*1024;
private static final ThreadLocal<IntPtr> SINGLE_VALUE =
new ThreadLocal<IntPtr>() {
#Override
protected IntPtr initialValue() {
return Struct.allocate(IntPtr.class, 1);
}
};
private static final ThreadLocal<BytePtr> INFO_LOG =
new ThreadLocal<BytePtr>() {
#Override
protected BytePtr initialValue() {
return Struct.allocate(BytePtr.class, MAX_INFO_LOG_LENGTH);
}
};
static {
Bro.bind(GLES20.class);
}
#Bridge
public static native void glClearColor(float red, float green, float blue, float alpha);
#Bridge
public static native void glClear(int mask);
#Bridge
public static native void glGetIntegerv(int pname, IntPtr params);
// DO NOT CALL THE NEXT METHOD WITH A pname THAT RETURNS MORE THAN ONE VALUE!!!
public static int glGetIntegerv(int pname) {
IntPtr params = SINGLE_VALUE.get();
glGetIntegerv(pname, params);
return params.get();
}
#Bridge
private static native int glGetUniformLocation(int program, BytePtr name);
public static int glGetUniformLocation(int program, String name) {
return glGetUniformLocation(program, BytePtr.toBytePtrAsciiZ(name));
}
#Bridge
public static native int glGenFramebuffers(int n, IntPtr framebuffers);
public static int glGenFramebuffer() {
IntPtr framebuffers = SINGLE_VALUE.get();
glGenFramebuffers(1, framebuffers);
return framebuffers.get();
}
#Bridge
private static native void glShaderSource(int shader, int count, BytePtrPtr string, IntPtr length);
public static void glShaderSource(int shader, String code) {
glShaderSource(shader, 1, new BytePtrPtr().set(BytePtr.toBytePtrAsciiZ(code)), null);
}
#Bridge
private static native void glGetShaderInfoLog(int shader, int maxLength, IntPtr length, BytePtr infoLog);
public static String glGetShaderInfoLog(int shader) {
BytePtr infoLog = INFO_LOG.get();
glGetShaderInfoLog(shader, MAX_INFO_LOG_LENGTH, null, infoLog);
return infoLog.toStringAsciiZ();
}
#Bridge
public static native void glGetShaderPrecisionFormat(int shaderType, int precisionType, IntBuffer range, IntBuffer precision);
#Bridge
public static native void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, IntBuffer data);
#Bridge
private static native void glVertexAttribPointer(int index, int size, int type, int normalized, int stride, Buffer pointer);
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, Buffer pointer) {
glVertexAttribPointer(index, size, type, normalized ? GL_TRUE : GL_FALSE, stride, pointer);
}
}
Note how most methods are exposed via just trivial #Bridge-annotated native definitions, but for some it's convenient to define a wrapper method in Java that converts a String to a *char or unpacks a result from an IntPtr for example.
I didn't post my whole library file, since it is still very incomplete and it'll just make it harder to find the examples of how different parameter types are handled.
To save yourself some work, you can copy the GL constant definitions from libGDX's GL20.java. And the OpenGL ES docs are a great reference for the calling signature of the methods (the data types GLenum and GLbitfield correspond to a Java int).
You can then call the gl-methods statically by prepending GLES20. (just like on Android), e.g.:
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Turns out Bro is so smart that you don't even need to include the <framework>OpenGLES</framework> tag in robovm.xml any more, like you would with libGDX.
And - What do you know? - my app starts about 3 times as quickly as it did when it was still using libGDX. And it fixed another issue I had (see LibGDX displays black screen while app is paused but still visible (e.g. during in-app purchase password dialog) on iOS). "Yay!" for getting rid of unnecessary baggage.
The one thing that makes life a little annoying is that if you mess up the call signature of a method or the memory allocation, your app will simply crash with a very unhelpful "Terminated due to signal 11" message in the IDE-console that contains no information about where the app died.

How to create and using vapi files?

I want to make a custom vapi file, I have the basic stuff but I obviously miss something and I can't find anywhere how to do this properly. My main goal is to create a torent app, using libtorrent, and create the GUI (the frontend?) with vala and gtk.
I have a c_func_head.h:
#ifndef WHATEVER_H_INCLUDED
#define WHATEVER_H_INCLUDED
int add(int a, int b);
#endif
c_functions.c:
#include <stdio.h>
#include <stdlib.h>
#include "c_func_head.h"
int add(int a, int b){
printf("Adding numbers in c...\n");
return a+b;
}
vala_p.vapi:
[CCode (cheader_filename = "c_func_head.h")]
namespace MyFunc {
[CCode (cname = "add")]
public int add (int a, int b);
}
and finally vala_program.vala:
//extern int add(int a, int b);
using MyFunc;
void main(){
stdout.printf("Calling a c function...\n");
//stdout.printf("The sum is: %d\n", add2number(2, 2));
int sum = add(2, 2);
stdout.printf("The sum is: %d\n", sum);
}
As you can see I used an extern too, it worked with it but I want to use vapi files.
I compiled with (everything is in the same folder):
valac vala_program.vala --vapidir=vala_p.vapi -o mustrun
and the error is:
The namespace name `MyFunc' could not be found using MyFunc;
One more thing. Is it possible to make bindings for libtorrent? It uses c++ and I gues I have to use c++ too.
You can't make Vala bindings of C++ code. Only C. There a a guide to writing legacy bindings and a binding for Transmission, which is C-based.
As for the specific error you have, you want to call valac vala_program.vala vala_p.vapi if the library (i.e., header files) are the the same directory or valac vala_program.vala --pkg vala_p --vapidir=/path/to/directory/containing/vapi.

Purpose of lua_lock and lua_unlock?

What is the point of lua_lock and lua_unlock?
The following implies it's important:
LUA_API void lua_gettable (lua_State *L, int idx) {
StkId t;
lua_lock(L);
t = index2adr(L, idx);
api_checkvalidindex(L, t);
luaV_gettable(L, t, L->top - 1, L->top - 1);
lua_unlock(L);
}
LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
StkId t;
TValue key;
lua_lock(L);
t = index2adr(L, idx);
api_checkvalidindex(L, t);
setsvalue(L, &key, luaS_new(L, k));
luaV_gettable(L, t, &key, L->top);
api_incr_top(L);
lua_unlock(L);
}
The following implies it does nothing:
#define lua_lock(L) ((void) 0)
#define lua_unlock(L) ((void) 0)
Please enlighten.
If you port Lua to another platform, you are "allowed" to overwrite lua_lock with your own definition; and this definition should essentially be a mutex, to disallow cross-thread operations on the same Lua objects. Essentially, when implemented, it should act similarly to Python's Global Interpreter Lock (GIL).
It's defined to a no-op in vanilla Lua, because vanilla Lua is 100% ANSI-C and runs in a single thread: there's no need for any locking mechanism to be implemented. However, the developers chose to put the lock statements in there for people who port Lua and implement threading in the interpreter.
Sources:
Proposal: fast lua_lock
Why write lua_unlock before lua_lock?
Mailing list

Resources