Calling a dll created in VB6 from F# - 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)

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.

DllImport in FSI

Need to port following C# code to F#:
[DllImport("libc", SetLastError = true)]
private static extern int chmod(string pathname, int mode);
What is wrong in following code? Tried it in FSI on Mac and getting error FS0193: internal error: Method 'FSI_0020+Libc.chmod' does not have a method body.
module Libc =
open System.Runtime.InteropServices
[<DllImport("libc", SetLastError = true)>]
extern int chmod(string pathname, int mode)
[<DllImport ("libc", EntryPoint = "chmod", SetLastError = true)>]
extern int sys_chmod (string _path, uint32 _mode)
let chmodCarry mode path = sys_chmod(path, mode)
And what to do with private and static in this case? I would make sys_chmod private and expose the carried chmod function only.
Or is there any other more portable way to make a file executable?

How to discover lock declaration instruction in llvm?

I'm new to llvm , and was trying to find lock declaration statement and then do some instrumention work,the code like this:
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
int share = 42;
mutex m;
void f()
{
m.lock();
--share;
cout << "function f -> share: " << share << '\n';
m.unlock();
}
int main()
{
thread thf{f};
thf.join();
return 0;
}
I want to find the lock declaration instruction eg:
mutex m;
the llvm instrumention pass like this:
struct SkeletonPass : public FunctionPass {
static char ID;
SkeletonPass() : FunctionPass(ID) {}
virtual bool runOnFunction(Function &F) {
// Get the function to call from our runtime library.
LLVMContext &Ctx = F.getContext();
Constant *logFunc = F.getParent()->getOrInsertFunction(
"logop", Type::getVoidTy(Ctx), Type::getInt32Ty(Ctx), NULL
);
for (auto &B : F) {
for (auto &I : B) {
***if ((&I) is lock declaration instruction)*** {
// Insert something *after* `op`.
IRBuilder<> builder(op);
builder.SetInsertPoint(&B, ++builder.GetInsertPoint());
// Insert a call to function.
builder.CreateCall(logFunc, ConstantInt::get(Type::getInt32Ty(Ctx), 2));
return true;
}
}
}
In short, could you please tell me how to discover lock declaration instruction, thanks!
The declaration would appear as a global, so you should write a module pass to find it, not a function pass. It should appear as something like:
#m = global %mutex zeroinitializer
In fact, using the demo at http://ellcc.org/demo/index.cgi to try this, you can indeed see that:
...
%"class.std::__1::mutex" = type { %struct.pthread_mutex_t }
%struct.pthread_mutex_t = type { %union.anon }
%union.anon = type { [5 x i8*] }
...
#m = global %"class.std::__1::mutex" zeroinitializer, align 8
You can use LLVM's CppBackend to compile your code. This would produce a C++ code that makes up the source. You can then easily find out how mutex m; definition is constructed via LLVM API.
Run clang -march=cpp foo.cpp to use CppBackend. Alternatively, you can use this demo page to compile your code online.

Wrapping a DLL import in a module in 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.

MSBuild fails to see environment variable that is set from build workflow

This is related to TFS 2010 Build System. Within our build workflow we set a couple of environment variables using the SetEnvironmentVariable method of System.Environment class. I have confirmed that this environment variable gets set properly on the build server and that it gets set as a system wide environment variable.
The problem is that when MSBuild gets invoked within this WF and it compiles the solutions, our post build events which tries to read this environment variable fail as they are unable to see this environment variable.
Is there a way to force MSBuild to reload environment variables or force a running WF to reload environment variables? My suspicion is that even though WF creates this variable, it does not refresh its Environment state and hence can not see the variable. Further since the WF invokes MSBuild, it passes the same environment state to MSBuild which does ont contain this variable.
Update
Stick the following code in Visual Studio and run it. The delay to SendMessageTimeOut is 10 second so be patient.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.ComponentModel;
namespace EnvironmentVarTest
{
class Program
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool
SendMessageTimeout(
IntPtr hWnd,
int Msg,
int wParam,
string lParam,
int fuFlags,
int uTimeout,
out int lpdwResult
);
public const int HWND_BROADCAST = 0xffff;
public const int WM_SETTINGCHANGE = 0x001A;
public const int SMTO_NORMAL = 0x0000;
public const int SMTO_BLOCK = 0x0001;
public const int SMTO_ABORTIFHUNG = 0x0002;
public const int SMTO_NOTIMEOUTIFNOTHUNG = 0x0008;
static void Main(string[] args)
{
Program p = new Program();
string environmentVariableValue = DateTime.Now.ToLongTimeString().Replace(":", String.Empty);
Console.WriteLine("On the CMD window that opens up after about 10 seconds, if you type %samplevar% and hit Enter, you should see: " + environmentVariableValue);
p.SetEnvironmentVariable(environmentVariableValue);
RefreshProcessVars();
p.ReadEnvironmentVariable();
p.StartCMD();
Console.ReadLine();
}
void SetEnvironmentVariable(string value)
{
System.Environment.SetEnvironmentVariable("samplevar", value, EnvironmentVariableTarget.Machine);
}
static void RefreshProcessVars()
{
int result;
bool callresult = SendMessageTimeout(
(System.IntPtr)HWND_BROADCAST,
WM_SETTINGCHANGE,
0,
"Environment",
SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG,
10000,
out result);
if (!callresult || result == 0)
{
int lasterror = Marshal.GetLastWin32Error();
Win32Exception winex = new Win32Exception(lasterror);
Console.WriteLine("Exception happened while calling SendMessageTimeOut. The exception message is " + winex.Message);
}
}
void ReadEnvironmentVariable()
{
var x = System.Environment.GetEnvironmentVariable("samplevar", EnvironmentVariableTarget.Machine);
}
void StartCMD()
{
Process.Start("cmd.exe");
}
}
}
Unfortunately, because the MSBuild process is passed a cached version of the environment variables when it's started up, the command-line functionality of that process will not be able to see the updated values. The best bet you've got, in my opinion, is to either change that variable in the post-build event or store the value in a medium that you can read from the post-build event.
Update
Okay, so the statement below (which can be found here) I think explains where the environment variables are coming from and why you're not getting an updated version in MSBuild.
By default, a child process inherits the environment variables of its parent process.
So, two can play at that game, let's just broadcast that a change has occurred and see if that will take care of it for us. Below is the code that should do that for you.
[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return:MarshalAs(UnmanagedType.Bool)]
public static extern bool
SendMessageTimeout(
IntPtr hWnd,
int Msg,
int wParam,
string lParam,
int fuFlags,
int uTimeout,
out int lpdwResult
);
public const int HWND_BROADCAST = 0xffff;
public const int WM_SETTINGCHANGE = 0x001A;
public const int SMTO_NORMAL = 0x0000;
public const int SMTO_BLOCK = 0x0001;
public const int SMTO_ABORTIFHUNG = 0x0002;
public const int SMTO_NOTIMEOUTIFNOTHUNG = 0x0008;
int result;
SendMessageTimeout(
(System.IntPtr)HWND_BROADCAST,
WM_SETTINGCHANGE,
0,
"Environment",
SMTO_BLOCK | SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG,
SomeTimeoutValue,
out result);

Resources