2011-09-09 3 views
2

C (P/호출)에 C 번호에서 다른 구조의 배열 구조를 통과 :I는 다음의 구조를 한

[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 long 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 */ 
}; 
[StructLayout(LayoutKind.Sequential)] 
public struct TRatePt 
{ 
    public long fDate; 
    public double fRate; 
}; 

TRatePt 같이 정의는 다음과

[DllImport("alib.dll", EntryPoint = "GtoCapFloorAvgVol")] 
    public static extern int CapFloorAvgVol(
     long capStartDate,     /* (I) */ 
     long capExpiryDate,     /* (I) */ 
     double[] strikeRates,    /* (I) */ 
     int numStrikeRates,     /* (I) */ 
     double[] principles,     /* (I) */ 
     int numPrinciples,     /* (I) */ 
     int moneymarketDen,     /* (I) # days/year */ 
     ref TDateInterval resetPeriod,  /* (I) Time Between caplets */ 
     int optionType,      /* (I) Cap or Floor */ 
     char stubPosition,     /* (I) 2/16/94 GG 'F'ront or 'B'ack */ 
     [In] IntPtr zeroCurve,    /* (I) For discounting Pointer to TCurve*/ 
     double price,      /* (I) Price */ 
     double avgVolGuess,     /* (I) Average Volatility guess */ 
     out double avgVol);     /* (O) Average Volatility */ 

ㄴ 선언 is :

GTO_EXPORT(int) GtoCapFloorAvgVol(
TDate capStartDate,     /* (I) */ 
TDate capExpiryDate,     /* (I) */ 
double *strikeRates,     /* (I) */ 
int numStrikeRates,     /* (I) */ 
double *principles,     /* (I) */ 
int numPrinciples,     /* (I) */ 
int moneymarketDen,     /* (I) # days/year */ 
TDateInterval *resetPeriod,   /* (I) Time Between caplets */ 
int optionType,      /* (I) Cap or Floor */ 
char stubPosition,     /* (I) 2/16/94 GG 'F'ront or 'B'ack */ 
TCurve *zeroCurve,     /* (I) For discounting */ 
double price,      /* (I) Price */ 
double avgVolGuess,     /* (I) Average Volatility guess */ 
double *avgVol)      /* (O) Average Volatility */ 

미리 감사드립니다.

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 구조체이다 당신이 * 도움이 될 것 환영 공백을 처리하는 방법을 알고 있다면 ...

typedef struct{ 
TDate fDate; 
double fRate;} TRatePt; 

그런데

추신 : TDate는 typedef long int TDate;

입니다. 그것을 사용하십시오 :

TCurve _zeroCurve = new TCurve() 
         { 
          fBaseDate = _tempValueDate, 
          fNumItems = _ratePoints.Length, 
          fBasis = 2L, 
          fDayCountConv = 1 
         }; 
     int _sizeOfTCurve = Marshal.SizeOf(typeof(TCurve)); 
     IntPtr p_zeroCurve = Marshal.AllocHGlobal(_sizeOfTCurve); 
     Marshal.StructureToPtr(_zeroCurve, p_zeroCurve, false); 

     int _status; 
     _zeroCurve.fArray = Marshal.AllocHGlobal(_ratePoints.Length * Marshal.SizeOf(typeof(TRatePt))); 
     try 
     { 
      IntPtr _ratePt = _zeroCurve.fArray; 
      for (int _i = 0; _i < _ratePoints.Length; _i++) 
      { 
       Marshal.StructureToPtr(_ratePoints[_i], _ratePt, false); 
       //_ratePt = new IntPtr(_ratePt.ToInt64() + Marshal.SizeOf(typeof(TRatePt))); 
       IntPtr _nextRatePt = new IntPtr(_ratePt.ToInt64() + Marshal.SizeOf(typeof(TRatePt))); 
       _ratePt = _nextRatePt; 
       //_ratePt += Marshal.SizeOf(typeof(TRatePt)); 
      } 
      _status = CapFloorAvgVol(_tempStartDate, _temPexpiryDate, strikeRates, strikeRates.Length, principles, principles.Length, moneymarketDen, 
              ref _resetPeriod, optionType, stubPosition, p_zeroCurve, price, avgVolGuess, out avgVol); 
     } 
     finally 
     { 
      Marshal.FreeHGlobal(_zeroCurve.fArray); 
     } 

     Marshal.FreeHGlobal(p_zeroCurve); 
     p_zeroCurve = IntPtr.Zero; 
+0

당신은 구조체에 대한 우리에게 C 선언을 줄 수 있습니까? –

+0

또한 C에서'long'은 C#에서'int'를 의미합니다. C에서'long long'은 C#에서'long'입니다. –

+0

위 구조체를 추가했습니다 – nche

답변

2

좋아요, 당신이 의미하는 것만 큼하는 방법은 여기 있습니다, 그리고 그것을 해결하는 데 너무 오래 걸렸습니다. TCurve에 대한 포인터는 수동 마샬링을 사용해야합니다.

편의를 위해 구조를 단순화했습니다.

[StructLayout(LayoutKind.Sequential)] 
public struct TCurve 
{ 
    public int fNumItems;    
    public IntPtr fArray;//you need to marshal this manually 
}; 
... 
[DllImport("alib.dll", EntryPoint = "GtoCapFloorAvgVol")] 
public static extern int CapFloorAvgVol(
    ... 
    TCurve ref zeroCurve, 
    ... 
); 
... 
TCurve curve = new TCurve(); 
TRatePt[] items = new TRatePt[2]; 
//for example, but you'd have the items coming in as a parameter I guess 

curve.fNumItems = items.Length; 
curve.fArray = Marshal.AllocHGlobal(items.Length * Marshal.SizeOf(typeof(TRatePt))); 
try 
{ 
    IntPtr item = curve.fArray; 
    for (int i = 0; i < items.Length; i++) 
    { 
     Marshal.StructureToPtr(items[i], item, false); 
     item = new IntPtr(item.ToInt64() + Marshal.SizeOf(typeof(TRatePt))); 
    } 
    //now call the function passing the curve struct 
} 
finally 
{ 
    Marshal.FreeHGlobal(curve.fArray); 
} 

나는 Pack = 1이 정확한지 의심 스럽다. 그것은 또 다른 문제가 long 64 C#에서 비트 만 long int, long, int Windows에서 C++의 모든 32 비트있는 점이다 C.

에서 구조체 팩을 꽤 드문.

마지막으로 void* 매개 변수는 불투명 한 포인터이므로 C# 구조체에 IntPtr으로 선언해야합니다.

+0

에 있습니다. TCurve를 함수에 전달하려면이 작업을 수행해야합니까? – nche

+0

물론 가능합니다! TCurve는 다른 모든 필드도 가지고 있습니다. 나는 방금 그들을 제거하고 당신이 붙어 있던 조금에 집중했다. –

+0

죄송합니다. IntPtr로 전달해야하거나 Ref TCurve ok입니까? – nche

0

안전하지 않은 구조체로 작동하지 않습니까?

[StructLayout(LayoutKind.Sequential)] 
public unsafe struct TCurve 
{ 
    public TRatePt* fArray;   /* Dates & rates */ // pointer to an array of TRatePt[] 
}; 
[StructLayout(LayoutKind.Sequential)] 
public unsafe struct TRatePt 
{ 
    public long fDate; 
    public double fRate; 
}; 

그리고, 당신의 코드에서 :

unsafe 
{ 
    TCurve _zeroCurve = new TCurve(); 
    var arr = new TRatePt[]{new TRatePt(), new TRatePt()}; 
    fixed (TRatePt* pt = arr) 
    { 
      _zeroCurve.fArray = pt; 
      // do sthing while your array is fixed 
    } 
} 
+0

시도하지 않았지만 안전하지 않은 코드로 작업하지 않는 것이 좋습니다. 어쨌든, @ JonathanDisckon 덕분에 문제가 해결되었습니다. – nche

관련 문제