Recent

Author Topic: C#/Mono and FPC library - correct way to pass a double[] to library  (Read 10629 times)

BadProgrammer

  • Newbie
  • Posts: 5
Hello.
I have a C# program, which controls a experiment and gets data to double[] arrays. Those arrays are dynamic - there is no known size.
I should create a DLL in free pascal which should calculate one parameter from those arrays and return back.
Example code of simple DLL:
Code: [Select]
library solidity;

type

TDynArray = array[0..65536] of double;

function taramasalata ( TimeArray: TDynArray; ValueArray : TDynArray) : double; cdecl; {Linux/Unix -cdecl, Windows - sdtcal}

var

    LengthOfArray : integer;
    L1, L2 : integer;
    i : integer;
begin
    i :=0;
    taramasalata:= TimeArray[0] + ValueArray[1];
end;


exports
    taramasalata;

end.

Example code of C#:

Code: [Select]
using System;
using Gtk;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Globalization;

public partial class MainWindow: Gtk.Window
{
const string SimpLibName = "libtarama.dll";

//Declare external functions using the DllImport attribute.
[DllImport(SimpLibName, EntryPoint="taramasalata", CharSet=CharSet.Auto,
           CallingConvention=CallingConvention.Cdecl)]
public static extern double rmSuoliai ([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] double[] TimeArray, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] double[] ValueArray);

public MainWindow (): base (Gtk.WindowType.Toplevel)
{
Build ();
}

protected void OnDeleteEvent (object sender, DeleteEventArgs a)
{
Application.Quit ();
a.RetVal = true;
}

protected void OnPressBtnClicked (object sender, EventArgs e)
{

try {
string[] Timelist = array1.Buffer.Text.Split ('\n');

List<double> TimeArray = new List<double> ();
string[] ValueList = array2.Buffer.Text.Split ('\n');
List<double> ValueArray = new List<double> ();
foreach (string s in Timelist) {
TimeArray.Add (Convert.ToDouble (s, CultureInfo.InvariantCulture));
}
foreach (string m in ValueList) {
ValueArray.Add (Convert.ToDouble (m, CultureInfo.InvariantCulture));
}
//call to dll:
double answer = taramasalata (TimeArray.ToArray (), ValueArray.ToArray ());
answer42.Text = Convert.ToString (answer, CultureInfo.InvariantCulture);
} catch (Exception ex) {
Console.WriteLine (ex.ToString ());
}
}
}


Question:

How to pass a double[] to DLL? Those duoble[] arrays are dynamically.
« Last Edit: January 26, 2014, 07:47:41 pm by BadProgrammer »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12765
  • FPC developer.
Re: C#/Mono and FPC library - correct way to pass a double[] to library
« Reply #1 on: January 26, 2014, 05:59:01 pm »
COM compatible safearrays? There are functions to construct those in either unit variants or varutils

BadProgrammer

  • Newbie
  • Posts: 5
Re: C#/Mono and FPC library - correct way to pass a double[] to library
« Reply #2 on: January 26, 2014, 06:45:21 pm »
Excuse me, but I'm not so good to know about COM objects. Could you provide a working example?
Secondary, I'm writing with a Mono/C# - there is no COM support...

COM compatible safearrays? There are functions to construct those in either unit variants or varutils

hinst

  • Sr. Member
  • ****
  • Posts: 303
Re: C#/Mono and FPC library - correct way to pass a double[] to library
« Reply #3 on: January 26, 2014, 07:20:29 pm »
You already did everything you had to by this code:
Code: [Select]
//Declare external functions using the DllImport attribute.
[DllImport(SimpLibName, EntryPoint="taramasalata", CharSet=CharSet.Auto,
           CallingConvention=CallingConvention.Cdecl)]
public static extern double rmSuoliai ([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] double[] TimeArray, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] double[] ValueArray);
This should take care of everything. Did you try running your program?
Perhaps you should call your imported function like this:
double answer = rmSuoliai (TimeArray.ToArray (), ValueArray.ToArray ());
not
double answer = taramasalata (TimeArray.ToArray (), ValueArray.ToArray ());
Try this and see if it works; don't forget to put dynamic library to the same folder where .net executable is
Too late to escape fate

BadProgrammer

  • Newbie
  • Posts: 5
Re: C#/Mono and FPC library - correct way to pass a double[] to library
« Reply #4 on: January 26, 2014, 08:06:18 pm »
I've corrected all posts and I've inspected my code - there are no mistypes -  it compiles without issues. But my code is not running.

BadProgrammer

  • Newbie
  • Posts: 5
Re: C#/Mono and FPC library - correct way to pass a double[] to library
« Reply #5 on: January 27, 2014, 11:40:07 am »
Again.

This is new post because of new problem but related to DLL and C#.

I tried to make a workaround to my problem with double[]. I wrote this array to file and I've tried to create simple DLL which would access to this file and count line numbers.

DLL's code:

Code: [Select]
library Answer;

Uses sysutils;

function getAnswer ( FileName : String):integer; cdecl;

var
        i : integer; 
        f1 : TextFile;     
begin
        try
                i:=0;
                Assign(f1, FileName);
                Reset(f1);
                while not EOF(f1) do
                        begin
                                ReadLn(f1);
                                i := i + 1;
                        end;
                Close(f1);
                getAnswer := i;
        except
                on E: EInOutError do
                begin
                i:=1024;
                end;
        end;
end;

exports
        getAnswer;
end.

there is a C# code:

Code: [Select]
using System;
using Gtk;
using System.Globalization;
using System.Runtime.InteropServices;

public partial class MainWindow: Gtk.Window
{
const string SimpLibName = "libAnswer.dll";
[DllImport(SimpLibName, EntryPoint="getAnswer",
             CallingConvention=CallingConvention.Cdecl)]
             public static extern int getAnswer(string FileName);
 
public MainWindow (): base (Gtk.WindowType.Toplevel)
{
Build ();
}

protected void OnDeleteEvent (object sender, DeleteEventArgs a)
{
Application.Quit ();
a.RetVal = true;
}
protected void OnButton1Clicked (object sender, EventArgs e)
{
try {
string FileName = FileNameEntry.Text ;
//call to dll:
int answer = getAnswer(FileName);
AnswerEntry.Text = Convert.ToString(answer, CultureInfo.InvariantCulture);
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
}

}

My Programm crashes with

Quote
Thread 1 (Thread 0x7f026dc22780 (LWP 18849)):
#0  0x00007f026d105c9d in read () at ../sysdeps/unix/syscall-template.S:81
#1  0x000000000049d7ab in ?? ()
#2  0x00000000004ee15b in ?? ()
#3  0x00000000004220cd in ?? ()
#4  <signal handler called>
#5  0x00007f0256168d5b in SYSTEM_WAITFREE_VAR$PMEMCHUNK_VAR () from /home/user/Workspace/pascalproj/l1/libraryTest/libraryTest/bin/Debug/libAnswer.dll
#6  0x0000000000000000 in ?? ()

=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================

Question:

Whats wrong with my code? In some cases my program calculates two or three times lines of file and crashes too.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12765
  • FPC developer.
Re: C#/Mono and FPC library - correct way to pass a double[] to library
« Reply #6 on: January 27, 2014, 11:45:58 am »

Whats wrong with my code? In some cases my program calculates two or three times lines of file and crashes too.

You assume a FPC/Delphi "string" type is the same as a C# string. It isn't.

BadProgrammer

  • Newbie
  • Posts: 5
Re: C#/Mono and FPC library - correct way to pass a double[] to library
« Reply #7 on: January 27, 2014, 11:55:35 am »
 :o

Could You explain a little bit more?


Whats wrong with my code? In some cases my program calculates two or three times lines of file and crashes too.

You assume a FPC/Delphi "string" type is the same as a C# string. It isn't.

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: C#/Mono and FPC library - correct way to pass a double[] to library
« Reply #8 on: January 27, 2014, 03:21:47 pm »
Try the following:
Code: [Select]
library solidity;
type
TDynArray = array[0..65536] of double;

function taramasalata (const TimeArray: TDynArray; const  ValueArray : TDynArray) : double; cdecl; {Linux/Unix -cdecl, Windows - sdtcal}
P.S. type name TDynArray is misleading, since you're using static arrays. But using static arrays in this case (of messing with C# code) is correct.

« Last Edit: January 27, 2014, 03:23:18 pm by skalogryz »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12765
  • FPC developer.
Re: C#/Mono and FPC library - correct way to pass a double[] to library
« Reply #9 on: January 27, 2014, 03:55:42 pm »
:o

Could You explain a little bit more?

Delphi function: function getAnswer ( FileName : String):integer; cdecl;      with Delphi string

then on the C# side, you declare it with C# string:

[DllImport(SimpLibName, EntryPoint="getAnswer",
             CallingConvention=CallingConvention.Cdecl)]
             public static extern int getAnswer(string FileName);

since C# doesn't know Delphi's string type. This is not correct. Probably needs something char[] based or so, but I'm not that home in interop.

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

exdatis

  • Hero Member
  • *****
  • Posts: 668
    • exdatis
Re: C#/Mono and FPC library - correct way to pass a double[] to library
« Reply #11 on: January 27, 2014, 04:13:34 pm »
BigChimp, thanks for the interesting information!

 

TinyPortal © 2005-2018