Need help properly calling a C function from Delphi - c

I am statically importing a dynamic library (DLL) within Delphi and attempting to access its functions.
Here is the specific C function deceleration that I am trying to access:
int flann_radius_search_double (flann_index_t index_ptr, /* the index */
double* query, /* query point */
int* indices, /* array for storing the indices found (will be modified) */
double* dists, /* similar, but for storing distances */
int max_nn, /* size of arrays indices and dists */
float radius, /* search radius (squared radius for euclidian metric) */
struct FLANNParameters* flann_params);
Here is my deceleration in Delphi:
function flann_radius_search_double(index_ptr: flann_index_t;
var query: double; var indices: longint; var dists: double;
max_nn: longint; radius: single; var flann_params: FLANNParameters): longint;
cdecl; external External_library Name 'flann_radius_search_double';
And I accessed the function like this:
type
TDoubleArray = array[0..1000] of double;
PDoubleArray = ^TDoubleArray;
TIntArray = array[0..1000] of Integer;
PIntArray = ^TIntArray;
...
... <other unrelated code>
var
Indicies:TIntArray;
PIndicies:PIntArray;
Dists:TDoubleArray;
PDists:PDoubleArray;
...
begin
...
PIndicies:=#Indicies;
PDists :=#Dists;
radius_s:=flann_radius_search_double(idx ,&PMyArray^[0,0],Pindicies^[0],&PDists^[0],1000,10,&DEFAULT_FLANN_PARAMETERS);
It is not working, and looks way off :*(
I would really appreciate some assistance!
Edit: I fixed the double/single mistake, but when I attempt to use #Indicies[0] instead of Indicies[0] I get an error:
Error: Call by var for arg no. 3 has to match exactly: Got "Pointer"
expected "LongInt"

Disclaimer: what is written below refers to the original version of the question before it was completely changed. In the original version the floating point parameters were all float. I would urge Mike to post the real code using copy/paste in order to avoid wasting people's time.
C float is equivalent to Delphi Single, the 4 byte floating point type. That's the main problem you have.
I personally would declare the arrays as PSingle or PInteger in the import declaration, rather than using var parameters. When passing single values by reference then var parameters is appropriate.
When calling the function I wouldn't use fixed dimensioned arrays. I would use dynamic arrays and SetLength. Pass the array then with PSingle(MyArray), or #MyArray[0], whichever you prefer.
I would prefer Integer to Longint since I believe that Integer most closely matches C int.
Your arrays are 1001 elements in size, you only need them to be 1000.
The struct is best passed by var as you have it in the import declaration, but not as you have it in the call. Since the code in your question doesn't quite match up I don't want to say anything more.
function flann_radius_search_double(
index_ptr: flann_index_t;
var query: Single;
indices: PInteger;
dists: PSingle;
max_nn: Integer;
radius: Single;
var flann_params: FLANNParameters
): Integer; cdecl; external External_library Name 'flann_radius_search_double';
...
var
indices: array of Integer;
dists: array of Single;
...
SetLength(indices, 1000);
SetLength(dists, 1000);
radius_s := flann_radius_search_double(
idx,
MyArray[0,0],
#indicies[0],
#dists[0],
1000,
10.0,
DEFAULT_FLANN_PARAMETERS
);

In Delphi, float maps to Single, not Double. So it becomes:
function flann_radius_search_double(index_ptr: flann_index_t;
var query: Single;
indices: PInteger; // array, so NOT a var parameter
dists: PSingle; // array, so NOT a var parameter
max_nn: Integer;
radius: Single;
var flann_params: FLANNParameters): Integer;
cdecl; etc...
You call it like:
const
CArraySize = 1000;
...
var
Indices: array[0..CArraySize - 1] of Integer;
Dists: array[0..CArraySize - 1] of Single;
begin
...
x := flann_radius_search_double(idx, yourQuery,
#Indices[0], #Dists[0], Length(Dists), yourRadius, yourFlannParams);

Related

Swift 5 Create 3D Array of Doubles And Pass To C Function

I need to call a legacy C function (from swift) that expects a 3D array of Doubles as an argument. I am fairly new to Swift and have begun converting a large ObjC and C code base written for iOS and Mac over to Swift. The C code does a lot of complex astronomical math and for which Swift is just too cumbersome. I will not convert those, but I need to use them from Swift
The C function is declared like this and the .H file is visible to swift:
void readSWEDayData(double dData[DATA_ROWS_PER_DAY][NUM_PLANET_ELEMENTS][NUM_ELEMENTS_PER_PLANET]);
The Constants used in the declaration are defined to be:
DATA_ROWS_PER_DAY = 1
NUM_PLANET_ELEMENTS = 35
NUM_ELEMENTS_PER_PLANET = 4
I am struggling with declaring the array of doubles in a way that Swift will allow to be passed to the C function. I've tried several approaches.
First Approach:
I declare the array and call it like so:
var data = Array(repeating: Double(EPHEMERIS_NA), count:Int(DATA_ROWS_PER_DAY * NUM_PLANET_ELEMENTS * NUM_ELEMENTS_PER_PLANET))
readSWEDayData(&data)
I get this error: Cannot convert value of type 'UnsafeMutablePointer' to expected argument type 'UnsafeMutablePointer<((Double, Double, Double, Double),...
Second Approach:
If I declare the array this way:
var data = [(Double, Double, Double, Double)](repeating: (EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA), count: Int(NUM_PLANET_ELEMENTS))
readSWEDayData(&data)
I get this error: Cannot convert value of type 'UnsafeMutablePointer<(Double, Double, Double, Double)>' to expected argument type 'UnsafeMutablePointer<((Double, Double, Double, Double),
So, how the heck does one declare a 3D Array in Swift of a specific size so that it can be passed to a C Function?
The function needs an UnsafeMutablePointer to a 35-tuple of things, where each of those things are 4-tuples of Doubles. Yes, C arrays translate to tuples in Swift, because Swift doesn't have fixed size arrays. You could do:
var giantTuple = (
(EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA),
(EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA),
(EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA),
// 32 more times...
)
readSWEDayData(&giantTuple)
But I don't think you'd like that. You can create an array, and use some pointer magic to convert that to a tuple, as discussed in this Swift Forums post. In fact, that post is highly relevant to your situation.
To save some typing, we can write some type aliases first:
typealias Tuple35<T> = (T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T)
typealias Double4x35 = Tuple35<(Double, Double, Double, Double)>
Then we can do:
var giantTuple = Array(repeating: (EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA), count: NUM_PLANET_ELEMENTS).withUnsafeBytes { p in
p.bindMemory(to: Double4x35.self)[0]
}
readSWEDayData(&giantTuple)
This works because tuples and arrays have essentially the same "layout" in memory.
Note that I "cheated" a little bit here, since DATA_ROWS_PER_DAY is 1, you can just create one such giantTuple, and get a pointer to it. However, if it is greater than 1, you'd have to do something like:
var giantTuples = Array(repeating:
Array(repeating: (EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA, EPHEMERIS_NA), count: NUM_PLANET_ELEMENTS).withUnsafeBytes { p in
p.bindMemory(to: Double4x35.self)[0]
},
count: DATA_ROWS_PER_DAY)
readSWEDayData(&giantTuples)
To convert from the giant tuple back to an array, you can do something like this:
// converting the first giantTuples in "giantTuples" as an example
let arrayOf4Tuples = asCollection(giantTuples[0], Array.init)
let finalArray = arrayOf4Tuples.map { asCollection($0, Array.init) }
// these are adapted from the Swift forum thread
// you'll need two of these, because you have 2 types of tuples
// yes, working with C arrays is hard :(
func asCollection<T, E>(_ tuple: Tuple35<E>, _ perform: (UnsafeBufferPointer<E>)->T) -> T {
return withUnsafeBytes(of: tuple) { ptr in
let buffer = ptr.bindMemory(to: (E.self))
return perform(buffer)
}
}
func asCollection<T, E>(_ tuple: (E, E, E, E), _ perform: (UnsafeBufferPointer<E>)->T) -> T {
return withUnsafeBytes(of: tuple) { ptr in
let buffer = ptr.bindMemory(to: (E.self))
return perform(buffer)
}
}
Because Swift 5 lacks support for interoperability with C language multi-dimensional Arrays of fixed size except via tuples of explicitly declared structure (See Sweeper's answer above) and which is something I wish to avoid to keep my code flexible for future changes to the C Library being used, I opted to write a wrapper for the C function and make it appear to Swift as a 1 dimensional array.
This was necessary because the Constants used in the C Code change when readSWEDayData increases the array sizes to support additional elements and tuple declarations like this:
let Double4x35 = Tuple35<(Double, Double, Double, Double)>
will DEFINITELY break in a way that will be hard to find:
So my C wrapper function looks like so:
void readSWEDayDataForSwift(double *dData) {
readSWEDayData((double (*)[NUM_PLANET_ELEMENTS][NUM_ELEMENTS_PER_PLANET])dData);
}
Making it easy to call it from Swift like so:
var data = Array(repeating: Double(EPHEMERIS_NA), count:Int(DATA_ROWS_PER_DAY * NUM_PLANET_ELEMENTS * NUM_ELEMENTS_PER_PLANET))
I was surprised that this far into Swift's evolution there is no better way to do this!
My two cents for others..Hoping will help.
I got a similar problem, but hope can save time for other.
I had to pass down:
path (from String to char *)
title (from String to char *)
columns ([String] to array of char *)
a counter
to sum up I had to call "C" function:
bool OpenXLSXManager_saveIn(const char * cFullPath,
const char * sheetName,
char *const columnTitles[],
double *const values[],
int columnCount);
I started from excellent:
// https://oleb.net/blog/2016/10/swift-array-of-c-strings/
expanded a bit:
public func withArrayOfCStringsAndValues<R>(
_ args: [String],
_ values: [[Double]],
_ body: ([UnsafeMutablePointer<CChar>?] , [UnsafeMutablePointer<Double>?] ) -> R ) -> R {
var cStrings = args.map { strdup($0) }
cStrings.append(nil)
let cValuesArrr = values.map { (numbers: [Double]) -> UnsafeMutablePointer<Double> in
let pointer = UnsafeMutablePointer<Double>.allocate(capacity: numbers.count)
for (index, value) in numbers.enumerated() {
pointer.advanced(by: index).pointee = value
}
return pointer
}
defer {
cStrings.forEach { free($0) }
for pointer in cValuesArrr{
pointer.deallocate()
}
}
return body(cStrings, cValuesArrr)
}
so I can call:
func passDown(
filePath: String,
sheetName:
String,
colNames: [String],
values: [[Double]]
) -> Bool
{
let columnCount = Int32(colNames.count)
return withArrayOfCStringsAndValues(colNames, values) {
columnTitles, values in
let retval = OpenXLSXManager_saveIn(filePath, sheetName, columnTitles, values, columnCount)
return retval
}
}
(SORRY for formatting, S.O. formatter has BIG issues ..)

Array declaration in Kotlin

The code below is an example for Array declaration in Kotlin,
fun main(args: Array<String>) {
var a = Array<Int>(2){0}
a[0] = 100
a[1] = 200
print(a[1])
}
Here variable a is an array of size 2 and having values 100 and 200 and it is printing the value of a[1] as 200.
My question is -> What is the role of "0" in var a = Array(2){0}?
I changed the value of "0" to some other integer value, still it is working fine, but i was not able to find the use case of it. Can anyone explain it?
Any help will be appreciated.
Thanks.
The 0 is what you initialize each element of your array (2 in your case) with, using the following constructor:
public inline constructor(size: Int, init: (Int) -> T)
You can make this visible by printing the array directly after its initialization:
var a = Array<Int>(2){0}
println(a.contentToString())
Please consider the use of arrayOf(0,0) for such a simple use case, which is more idiomatic.
Arrays in Kotlin are represented by the Array class, that has get and set functions (that turn into [] by operator overloading conventions), and size property, along with a few other useful member functions:
class Array<T> private constructor() {
val size: Int
operator fun get(index: Int): T
operator fun set(index: Int, value: T): Unit
operator fun iterator(): Iterator<T>
// ...
}
You can write
var a = Array(2){0}
Creates a new array with the specified [size], where each element is calculated by calling the specified
* [init] function. The [init] function returns an array element given its index.
public inline constructor(size: Int, init: (Int) -> T)
Read Arrays in Kotlin.

Using C functions in Swift that take functions as arguments

I'm writing a wrapper around a C mathematical library. Every function takes one or two functions as arguments. However, the arguments for those child functions (as well as the parent functions) are not Swifty -hence the wrapper.
I've cleaned up the example code to just show the three main pieces: the c-library function, the desired Swift function that would be passed to the wrapper (body not shown, but wrapping around the c-library function), and the required C function form.
//C library function, that calls the passed function dozens, hundreds or thousands of times, each time it changes the data provided in p, and uses the output from x
//The Swift arrays are passed as pointers, and the length of the and x array are m and n respectively
returnValue = cLibraryFunc(passedFunc, &p, &x, Int32(m), Int32(n), Int32(itmax), &opts, &info, &work, &covar, &adata)
//I would like to create a Swift function that would look like this (internals could be any myriad of things that takes inputs p and adata and returns data in x:
func desiredSwifty(p: inout [Double], x: inout [Double], m: Int, n: Int, adata: inout [Double]) {
//very simple example
//this example knows the length of p (so m as well)
//and assumes that adata length is the same as the x length (n)
//obviously, it could ifer m and n from p.count and x.count
for i in 0..<n {
x[i] = p[0] + p[1]*adata[i] + p[2]*pow(adata[i], 2)
}
}
//And the wrapper would "convert" it -internally- into the form that the C library function requires:
func requiredC(p: UnsafeMutablePointer<Double>?, x: UnsafeMutablePointer<Double>?, m: Int32, n: Int32, adata: UnsafeMutablePointer<Void>?) {
//same thing, but using pointers, and uglier
//first, have to bitcast the void back to a double
let adataDouble : UnsafeMutablePointer<Double> = unsafeBitCast(adata, to: UnsafeMutablePointer<Double>.self)
for i in 0..<Int(n) {
x![i] = p![0] + p![1]*adataDouble[i] + p![2]*pow(adataDouble[i], 2)
}
}
addition
I should add that I have access to the c source code, so I could possibly add some dummy parameters (possibly to find a way to pass context in). But given that the docs seem to indicate that one can't grab context with a c function pointer, this may be of no use.
(Note: the following example uses Swift 3 on Xcode 8 beta 2.)
Your question is about C functions taking another C function as an argument, so let us reduce the question to that problem. Here is a simple C function which takes a single argument which is
again a C function which takes a pointer to an array of doubles
and an integer count:
// cfunction.h:
void cFunc(void (*func)(double *values, int count));
// cfunction.c:
void cFunc(void (*func)(double *values, int count)) {
double x[] = { 1.2, 3.4, 5,6 };
func(x, 3);
}
This function is imported to Swift as
func cFunc(_ func: (#convention(c) (UnsafeMutablePointer<Double>?, Int32) -> Swift.Void)!)
Here #convention(c) declares the block to have C-style calling
conventions. In particular, from Swift you can pass only a global function or a closure which does not capture any context.
A simple example for a Swift wrapper is
func swiftyFunc(passedFunc: (#convention(c) (UnsafeMutablePointer<Double>?, Int32) -> Void)) {
cFunc(passedFunc)
}
which you can use like this:
func functionToPass(values: UnsafeMutablePointer<Double>?, count: Int32) {
let bufPtr = UnsafeBufferPointer(start: values, count: Int(count))
for elem in bufPtr { print(elem) }
}
swiftyFunc(passedFunc: functionToPass)
or with a closure argument:
swiftyFunc { (values, count) in
let bufPtr = UnsafeBufferPointer(start: values, count: Int(count))
for elem in bufPtr { print(elem) }
}
Do you know that you can get a mutable pointer to a var just by using the & operator? It does the "right thing" on arrays too.
func foo(_ x: UnsafeMutablePointer<Int>) {
print(x)
}
func bar(_ x: UnsafeMutablePointer<Int>) {
print(x)
}
var array = [0]
foo(&array)
var int = 0
bar(&int)
(Tested on Swift 2, but most likely still valid on Swift 3.)
I suspect that this could drastically reduce your need for wrappers.

Delphi - How to pass a 'Type' as a parameter

I would like to know if it is possible to pass a declared type (in this case a record) to my function. I would not even ask if it was not for the SizeOf() function, because it can take a type as a parameter.
I'm translating code from C and I would like to keep it as close to the original as possible.
The C program declares PushArray and PushStruct as macros. Since Delphi does not have macro support, I'm trying to turn them into functions.
I've googled this a bit and it seems that I could possible use generic types.
Like function PushStruct<T>(Arena : Pmemory_arena; dtype : <T>) but you can only use this in an OOP type application.
function PushSize_(Arena : Pmemory_arena; Size : memory_index) : pointer;
begin
Assert((Arena^.Used + Size) <= Arena^.Size);
Result := Arena^.Base + Arena^.Used;
Arena^.Used := Arena^.Used + Size;
end;
function PushStruct(Arena : Pmemory_arena; dtype : ?) : pointer;
begin
result := PushSize_(Arena, sizeof(dtype));
end;
function PushArray(Arena : Pmemory_arena; Count: uint32; dtype : ?) : pointer;
begin
result := PushSize_(Arena, (Count)*sizeof(dtype))
end;
Here is the original C code:
#define PushStruct(Arena, type) (type *)PushSize_(Arena, sizeof(type))
#define PushArray(Arena, Count, type) (type *)PushSize_(Arena, (Count)*sizeof(type))
void *
PushSize_(memory_arena *Arena, memory_index Size)
{
Assert((Arena->Used + Size) <= Arena->Size);
void *Result = Arena->Base + Arena->Used;
Arena->Used += Size;
return(Result);
}
The C code isn't passing a type to the function. The pre-processor is expanding the macro and computing the size. You can see that from the prototype of the function:
void *PushSize_(memory_arena *Arena, memory_index Size)
Since you don't have macros in Delphi, you cannot arrange a direct translation. Personally, if it were me I would not attempt to match the C code exactly. I'd pass the size and leave it to the caller to use SizeOf. I don't think that's a terrible burden. It still leaves you with something very close to a literal translation – all you are missing is the convenience macros.
If you wanted to use generics, you could do so, but it would require you to use a static method. For instance:
type
TMyClass = class
class function PushSize(Arena: Pmemory_arena; Size: memory_index): Pointer; static;
class function PushStruct<T>(Arena: Pmemory_arena): Pointer; static;
end;
....
class function TMyClass.PushSize(Arena: Pmemory_arena; Size: memory_index): Pointer;
begin
Result := ....;
end;
class function TMyClass.PushStruct<T>(Arena: Pmemory_arena): Pointer;
begin
Result := PushSize(Arena, SizeOf(T));
end;
If you want to return a typed pointer that would look like this:
type
TMyClass<T> = class
type P = ^ T;
class function PushSize(Arena: Pmemory_arena; Size: memory_index): Pointer; static;
class function PushStruct(Arena: Pmemory_arena): P; static;
end;
....
class function TMyClass<T>.PushSize(Arena: Pmemory_arena; Size: memory_index): Pointer;
begin
Result := ....;
end;
class function TMyClass<T>.PushStruct(Arena: Pmemory_arena): P;
begin
Result := PushSize(Arena, SizeOf(T));
end;
Obviously you'd know what name to use instead of TMyClass!
I'm not convinced that generics are a good fit here because I guess you are wanting as literal a translation as possible. I would not choose to use generics in this scenario.
You could "expand the macros" by simply declaring your own Push* funtions for each record type as needed:
type
// just guessing here...
PMemoryArena = ^TMemoryArena;
TMemoryArena = record
Base: Pointer;
Used: Cardinal;
Size: Cardinal;
end;
TMemoryIndex = Cardinal;
// 1st example record type
PMyRecord1 = ^TMyRecord1;
TMyRecord1 = record
I1: Integer;
I2: Integer;
end;
// 2nd example record type
PMyRecord2 = ^TMyRecord2;
TMyRecord2 = record
D1: Double;
D2: Double;
end;
function PushSize_(Arena: PMemoryArena; Size: TMemoryIndex): Pointer; inline;
begin
Assert(Arena^.Used + Size <= Arena^.Size);
Result := Pointer(NativeUInt(Arena^.Base) + Arena^.Used);
Inc(Arena^.Used, Size);
end;
function PushMyRecord1(Arena: PMemoryArena): PMyRecord1;
begin
Result := PMyRecord1(PushSize_(Arena, SizeOf(TMyRecord1)));
end;
function PushMyRecord2(Arena: PMemoryArena): PMyRecord2;
begin
Result := PMyRecord2(PushSize_(Arena, SizeOf(TMyRecord2)));
end;
It does seem kind of unnecessary.
why not, for example
function PushStruct(Arena : Pmemory_arena) : pointer;
begin
result := PushSize_(Arena, sizeof( Arena ));
end;

Array as an argument of a function

I have 2 2-dimensional arrays and a function.
I would like that function to take the array as an argument.
I tried code like this:
var array1:array[1..10,1..10] of integer;
array2:array[1..20,1..10] of integer;
function name(var my_array:array of array of integer, n:integer);
function name(var my_array:array[1..n,1..10] of integer;const n:integer);
But I got errors while trying to compile the code. Any tips?
If you would like me to paste error codes for each version please leave a comment with a request.
For
function name(var my_array:array of array of integer, n:integer);
The error code is: "Incompatible type for arg no. : Got "Array[0..10] of Array[0..10] of SmallInt", expected "Open array od SmallInt" every time I call the function.
You need to declare your own type, and then use that type as the parameter to your function. Instead of passing the array dimensions, use the Low and High functions from the System unit; they will work with both static (pre-declared) and dynamic arrays, and avoid hard-coding array sizes and iterators.
You want to avoid hard-coding integer indexes, becaue static arrays in Pascal don't have to start with index 0; the following is a perfectly legal Pascal array declaration, where the array bounds are from index -3 to 3:
var
Arr: array[-3..3] of Integer;
Here's an example using a dynamic array (array of array of Integer) that loops through the two dimensional array and sums the values; it initializes a 5 x 5 array, populates it with data, and then calls the SumTwoDimIntArray function to sum the values.
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TTwoDimIntArray = array of array of Integer;
function SumTwoDimIntArray(Arr: TTwoDimIntArray): Integer;
var
i, j: Integer;
begin
Result := 0;
for i := Low(Arr) to High(Arr) do
for j := Low(Arr[i]) to High(Arr[i]) do
Result := Result + Arr[i][j];
end;
var
MyArr: TTwoDimIntArray;
i, j: Integer;
begin
SetLength(MyArr, 5);
for i := Low(MyArr) to High(MyArr) do
begin
SetLength(MyArr[i], 5);
for j := Low(MyArr[i]) to High(MyArr[i]) do
MyArr[i][j] := j + 1;
end;
WriteLn(Format('Sum is %d', [SumTwoDimIntArray(MyArr)]));
ReadLn;
end.
You shuld use a new type in these situations . like the following:
Type
vector = array [1..20,1..20] of integer;
var array1:vector;
array2:vector;
function name(var my_array:vector, n:integer);
function name(var my_array:vector;const n:integer);

Resources