Here is my glue DLL code in (Microsoft) C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace DLL2_Call
{
public class DLL2
{
// Notice that the "public" extern reference builds the marshaling -- the reference,
// now public, is available as DLL2.DLL2_Func. There is no need for a cover up routine
// unless there is work to be done or naming conventions to be applied.
// Also note we are still in "DLL Purgatory" (not "DLL Hell") because the system
// does not move the (extern) unmanaged DLL into the output for us (yet). However
// when placed there it works correctly. The "..\\..\\..\\x64\\Debug\\DLL2.dll" works
// on temporary basis but does not land for external device........
// Furthermore note that this (here) is a "Class Library" with full C# class feed to the
// master project. The significance is that it DOES place properly when referenced (as
// opposed to the unmanaged DLL that does not) and furthermore it is the means by why
// one can easily mix Microsoft C# and the (Silver) Swift languages together, as this
// class library can compile the entire required fully C# portion of the program.
// It is similar to the J2i.Net.XInputWrapper code example which itself, whose XInput.cs
// file is the similar DllImport group for its (Microsoft) DLL's.
[DllImport("..\\..\\..\\x64\\Debug\\DLL2.dll")] // CANGE this back to local reference, FIX move there!!!!!!!!!!!!!!! ???
public static extern double DLL2_Func(double a, double b); // Must match contents of DLL.
//public static double DLL2_F(double a, double b)
//{
// return DLL2_Func( a, b );
//}
// https://msdn.microsoft.com/en-us/library/hk9wyw21(v=vs.110).aspx
[DllImport("..\\..\\..\\x64\\Debug\\DLL2.dll")] // CANGE this back to local reference, FIX move there!!!!!!!!!!!!!!! ???
public static extern double DLL2_ArrayFunc([In, Out] double[] a, int n); // Also match DLL
[DllImport("..\\..\\..\\x64\\Debug\\DLL2.dll")] // CANGE this back to local reference, FIX move there!!!!!!!!!!!!!!! ???
public static extern double DLL2_ArrayIOFunc([In, Out] double[] a, int n); // Also match DLL
public static double DLL2_ArrayFuncCall(double[] a)
{
return DLL2_ArrayFunc(a,a.Length);
}
public static double DLL2_ArrayIOFuncCall(double[] a)
{
return DLL2_ArrayFunc(a, a.Length);
}
}
}
And here is the actual C++ DLL:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
// On creating and calling unmanaged (64 bit) DLL:
// http://www.ni.com/white-paper/3056/en/
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
extern "C" __declspec(dllexport) double DLL2_Func(double a, double b);
extern "C" __declspec(dllexport) double DLL2_ArrayFunc(double a[], int n);
extern "C" __declspec(dllexport) double DLL2_ArrayIOFunc(double a[], int n);
double DLL2_Func(double a, double b) {
return a*b;
}
double DLL2_ArrayFunc(double a[], int n) {
double product = 1.0;
for (int i = 0; i < n; ++i) {
product *= a[i];
}
return product;
}
double DLL2_ArrayIOFunc(double a[], int n) {
double product = 1.0;
for (int i = 0; i < n; ++i) {
product *= a[i];
a[i] *= 3;
}
return product;
}
And the Swift code snipped that uses the “DLL2”:
let x = Math.Cos(π/2)
let y = Math.Cos(π)
let z = DLL2.DLL2_Func(2.0,π)
var a: Double[]! =[1.0, 2.0, 3.0, 4.0, 5.0] // Is this syntax legal portable Swift?
var ap=1.0
ap = DLL2.DLL2_ArrayFuncCall(a)
ap = DLL2.DLL2_ArrayFunc(a,a.Length) // Apparently the last 2 lines do the same thing
These are totally stupid examples, done to test simple function, array read, and array read/write. I’m not sure where I was at on making array read/write work, either. Also there is probably a better way. And indeed, if I can figure out how to write that glue directly in or associated with the Silver rather than the glue DLL, would save a lot of work.
AAAK! Notes in above, figured out that I don’t have to write the “glue” code function calls in most instances! Just used the intervening DLL to import the “real” DLL, so that the function call lines could be declared correctly – then the Swift imported them directly so I didn’t really need any glue code to pass values! However there was one example above where the C++ needed 2 arguments, and glue code used the internal array knowledge to collapse to one argument — so a bit of intervening glue code is still useful.
(Also note that this code is not production ready technique, as the DLL was referenced in its location at compile time not on a target system. The problem of including and positioning the DLL needs to be handled.)