简体   繁体   中英

array as function parameter c to c# confusion

I am trying to write a class in C# to use exports from a dll but I have run into a bunch of functions that have an array as a function parameter that I am not sure how handle. Below is an example.

How would I use this in function in C#? Specifically how to handle iymdf[]?

What is taking place when the function is called?

Does this seem correct?

[DllImport("libsofa.dll")]
public static extern int iauJdcalf(int ndp, double dj1, double dj2, ref int[] iymdf =       new int[4]);

example:

int __stdcall iauJdcalf(int ndp, double dj1, double dj2, int iymdf[4])
{
    int j, js;
    double denom, d1, d2, f1, f2, f;

    /* Denominator of fraction (e.g. 100 for 2 decimal places). */
    if ((ndp >= 0) && (ndp <= 9)) {
        j = 0;
        denom = pow(10.0, ndp);
    } else {
        j = 1;
        denom = 1.0;
    }

    /* Copy the date, big then small, and realign to midnight. */
    if (dj1 >= dj2) {
        d1 = dj1;
        d2 = dj2;
    } else {
        d1 = dj2;
        d2 = dj1;
    }
    d2 -= 0.5;

    /* Separate days and fractions. */
    f1 = fmod(d1, 1.0);
    f2 = fmod(d2, 1.0);
    d1 = floor(d1 - f1);
    d2 = floor(d2 - f2);

    /* Round the total fraction to the specified number of places. */
    f = floor((f1+f2)*denom + 0.5) / denom;

    /* Re-assemble the rounded date and re-align to noon. */
    d2 += f + 0.5;

    /* Convert to Gregorian calendar. */
    js = iauJd2cal(d1, d2, &iymdf[0], &iymdf[1], &iymdf[2], &f);
    if (js == 0) {
        iymdf[3] = (int) (f * denom);
    } else {
        j = js;
    }

    /* Return the status. */
    return j;
} 

function documentation:

/*
**  - - - - - - - - - -
**   i a u J d c a l f
**  - - - - - - - - - -
**
**  Julian Date to Gregorian Calendar, expressed in a form convenient
**  for formatting messages:  rounded to a specified precision.
**
**  This function is part of the International Astronomical Union's
**  SOFA (Standards Of Fundamental Astronomy) software collection.
**
**  Status:  support function.
**
**  Given:
**     ndp       int      number of decimal places of days in fraction 
**     dj1,dj2   double   dj1+dj2 = Julian Date (Note 1)
**
**  Returned:
**     iymdf     int[4]   year, month, day, fraction in Gregorian
**                        calendar
**
**  Returned (function value):
**               int      status:
**                          -1 = date out of range
**                           0 = OK
**                          +1 = NDP not 0-9 (interpreted as 0)
**
**  Notes:
**
**  1) The Julian Date is apportioned in any convenient way between
**     the arguments dj1 and dj2.  For example, JD=2450123.7 could
**     be expressed in any of these ways, among others:
**
**             dj1            dj2
**
**         2450123.7           0.0       (JD method)
**         2451545.0       -1421.3       (J2000 method)
**         2400000.5       50123.2       (MJD method)
**         2450123.5           0.2       (date & time method)
**
**  2) In early eras the conversion is from the "Proleptic Gregorian
**     Calendar";  no account is taken of the date(s) of adoption of
**     the Gregorian Calendar, nor is the AD/BC numbering convention
**     observed.
**
**  3) Refer to the function iauJd2cal.
**
**  4) NDP should be 4 or less if internal overflows are to be
**     avoided on machines which use 16-bit integers.
**
**  Called:
**     iauJd2cal    JD to Gregorian calendar
**
**  Reference:
** 
**     Explanatory Supplement to the Astronomical Almanac,
**     P. Kenneth Seidelmann (ed), University Science Books (1992),
**     Section 12.92 (p604).
**
**  This revision:  2010 July 27
**
**  SOFA release 2010-12-01
**
**  Copyright (C) 2010 IAU SOFA Board.  See notes at end.
*/

Drop the ref keyword from the C# declaration, it isn't correct. You also need to lose the initialization in the declaration, that's not supported syntax. Initialize the array before you make the call.

[DllImport("libsofa.dll")]
public static extern int iauJdcalf(int ndp, double dj1, double dj2, int[] iymdf);
...
    int[] arr = new int[] { 1, 2, 3, 4 };
    int retval = iauJdcalf(1, 2, 3, arr);

You'll be wanting a standard function call, depending on what you are doing. The function definition simply states "these are my inputs", then when you call it, you have to supply actual values. You don't recreate the function def.

[DllImport("libsofa.dll")]
myReturn = iauJdcalf(1, 2.0, 2.0, [1,2,3,4]);

Your function defines as returning an int, so we capture it with the myReturn variable, you'll need to declare it first of course. Then we supply an int, two doubles, and an array. You could also pass variables of those types, being careful to make sure your array is the same size as required.

Also, watch your pointers! If you pass a variable to c, it does a copy to the local variable defined in the function. If you give it a pointer, you need to declare it so in the function definition, and realize that we are now playing the pointer game.

Too answer my own question, I thought there would be more Marshaling stuff involved, but the below code gives a reasonable output.

    [DllImport("libsofa.dll")]
    public static extern int iauJdcalf(int ndp, double dj1, double dj2,    [MarshalAs(UnmanagedType.LPArray, SizeConst = 4)] int[] iymdf);

as well as this:

    [DllImport("libsofa.dll")]
    public static extern int iauJdcalf(int ndp, double dj1, double dj2, int[] iymdf);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM