Структура, объявленная в C #, переданная в качестве параметра out в код C, не изменяется (P / Invoke) - PullRequest
0 голосов
/ 12 сентября 2011

Вот проблема, с которой я столкнулся ... У меня есть следующая функция C:

GTO_EXPORT(int )  GtoCapFloorVCCustom(
   TDate   valueDate,        /* (I) value date */
   int     moneyMarketDen,   /* (I) 360 or 365 days */
   char   *optNameArr,       /* (I) array of opts types used (C or F)*/
   double *optVolArr,        /* (I) associated volatilities for opts */
   double *optStrikeArr,     /* (I) array of option strike rates */
   TDate  *optExpiryDateArr, /* (I) array of option expiration dates */
   char    periodType,       /* (I) reset period type */
   int     numCapFloor,      /* (I) num of options */
   double *futArr,           /* (I) array of prices on futures */
   TDate  *futDateArr,       /* (I) array of futures dates */
   double *optFutStrikeArr,  /* (I) array of strike prices for opts */
   double *optFutPriceArr,   /* (I) array of future quotes */
   char   *optFutNameArr,    /* (I) type of futures options */
   int     numOptFut,        /* (I) number of futures */
   double  volGuess,         /* (I) volatility guess */
   int     useDefault,       /* (I) use default case flag */
   int     volInterpMethod,  /* (I) interpolation method */
   TCurve *zeroCurve,        /* (I) zero curve */   
   double  meanRev,           /* (I) mean reversion coefficient */
   TCurve *result            /* (O) resulting TCurve */
   )
{
    int status = FAILURE;
    result = GtoCapFloorVC(valueDate,moneyMarketDen,optNameArr,optVolArr,optStrikeArr,optExpiryDateArr,periodType,numCapFloor,futArr,futDateArr,
        optFutStrikeArr,optFutPriceArr,optFutNameArr,numOptFut,volGuess,useDefault,volInterpMethod,zeroCurve,meanRev);
    if(result == NULL)
        return FAILURE;
    else
        return SUCCESS;
}

В C # она объявлена ​​следующим образом:

[DllImport("alib.dll", EntryPoint = "GtoCapFloorVCCustom")]
    private static extern int CapFloorVC(
       int valueDate,        /* (I) value date */
       int moneyMarketDen,   /* (I) 360 or 365 days */
       char[] optNameArr,       /* (I) array of opts types used (C or F)*/
       double[] optVolArr,        /* (I) associated volatilities for opts */
       double[] optStrikeArr,     /* (I) array of option strike rates */
       int[] optExpiryDateArr, /* (I) array of option expiration dates */
       char periodType,       /* (I) reset period type */
       int numCapFloor,      /* (I) num of options */
       double[] futArr,           /* (I) array of prices on futures */
       int[] futDateArr,       /* (I) array of futures dates */
       double[] optFutStrikeArr,  /* (I) array of strike prices for opts */
       double[] optFutPriceArr,   /* (I) array of future quotes */
       char[] optFutNameArr,    /* (I) type of futures options */
       int numOptFut,        /* (I) number of futures */
       double volGuess,         /* (I) volatility guess */
       int useDefault,       /* (I) use default case flag */
       int volInterpMethod,  /* (I) interpolation method */
       ref TCurve zeroCurve,        /* (I) zero curve */
       double meanRev,           /* (I) mean reversion coefficient */
       out TCurve result             /* (O) resulting TCurve */
       );

Структура TCurveв C:

typedef struct _TCurve
{
    int       fNumItems;     /* Number of TRatePts in fArray */
    TRatePt  *fArray;        /* Dates & rates */
    TDate     fBaseDate;     /* Discount date */ 
    double    fBasis;        /* Number compounding periods / year */
    long      fDayCountConv; /* How the year fraction is computed */
    void     *fClassHandle;  /* C++ class handle implementation */ 
} TCurve;

и в C #:

[StructLayout(LayoutKind.Sequential)]
public struct TCurve
{
    public int fNumItems;             /* Number of TRatePts in fArray */
    public IntPtr fArray;          /* Dates & rates */ // pointer to an array of TRatePt[]
    public int fBaseDate;            /* Discount date */
    public double fBasis;         //ZERO_CURVE_BASIS in capvoll.c which is #defined as ANNUAL_BASIS 1   /* Number compounding periods / year */
    public long fDayCountConv;   //ZERO_CURVE_DAY_COUNT_CONV in capvoll.c which is #defined as GTO_ACT_365F; = 2L /* How the year fraction is computed */
    public IntPtr     fClassHandle;  /* C++ class handle implementation */
};

Теперь вот проблема, когда я отлаживаю свой код и захожу в Cll, параметр результата содержит правильные значения передконец функции GtoCapFloorVCCustom (это гарантирует, что параметры хорошо переданы).

Но в C # у меня есть результат со всеми значениями, установленными в 0.0.Я забыл где-то сортировку?С уважением.

ИЗМЕНЕНИЯ:

Моя новая функция C:

GTO_EXPORT(int )  GtoCapFloorVCCustom(
   ...
   TCurve *result            /* (O) resulting TCurve */
   )
{
    int status = FAILURE;
    int i;
    TCurve * tempResult = GtoCapFloorVC(valueDate,moneyMarketDen,optNameArr,optVolArr,optStrikeArr,optExpiryDateArr,periodType,numCapFloor,futArr,futDateArr,
        optFutStrikeArr,optFutPriceArr,optFutNameArr,numOptFut,volGuess,useDefault,volInterpMethod,zeroCurve,meanRev);
    status = ( (tempResult == NULL) ? FAILURE : SUCCESS);

    for(i = 0; i < tempResult->fNumItems; ++i)
    {
        result->fArray[i].fDate = tempResult->fArray[i].fDate;
        result->fArray[i].fRate = tempResult->fArray[i].fRate;
    }
    result->fBaseDate = tempResult->fBaseDate;
    result->fBasis = tempResult->fBasis;
    result->fDayCountConv = tempResult->fDayCountConv;
    result->fNumItems = tempResult->fNumItems;

    GtoFreeTCurve(tempResult);

    return status;
}

Теперь у меня есть доступ к исключению System.AccessViolationException.Я также попытался результат-> fArray = tempResult-> fArray, но затем он указывает на исходный массив, а свободный удаляет его (нормально).Итак, как я могу скопировать элементы в fArray, поскольку вышеприведенное дает мне исключение ...

ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ: Итак, я разобрался со своей проблемой.У меня есть структура, объявленная следующим образом:

[StructLayout(LayoutKind.Sequential)]
    public struct TRatePt
    {
        public int fDate;
        public double fRate;
    };

TCurve.fArray фактически указывает на массив TRatePt, то есть: TRatePt [].Я создал метод в TCurve, который создает массив TRatePt из указателя:

public TRatePt[] GetRatePoints()
        {
            IntPtr _localFArray = fArray;
            TRatePt[] _ratePts = new TRatePt[fNumItems];
            for (int _i = 0; _i < _ratePts.Length; _i++)
            {
                _ratePts[_i] = (TRatePt)Marshal.PtrToStructure(_localFArray, typeof(TRatePt));
                _localFArray = new IntPtr(_localFArray.ToInt64() + Marshal.SizeOf(typeof(TRatePt)));
            }

            return _ratePts;
        }

Спасибо всем за вашу помощь.Привет

...