diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt
index 58c69b73..80bf0948 100644
--- a/ReleaseNotes.txt
+++ b/ReleaseNotes.txt
@@ -1,3 +1,5 @@
+* [MDAPI-171] [.NET] Optimize OptionChainsBuilder for performance in .NET compared to Java
+
## Version 2.6.0
* [MDAPI-96] [.NET] Retrieve latest events from feed
diff --git a/src/DxFeed.Graal.Net/DxFeed.Graal.Net.csproj b/src/DxFeed.Graal.Net/DxFeed.Graal.Net.csproj
index 291a91cb..9392d0d4 100644
--- a/src/DxFeed.Graal.Net/DxFeed.Graal.Net.csproj
+++ b/src/DxFeed.Graal.Net/DxFeed.Graal.Net.csproj
@@ -4,6 +4,8 @@
true
true
SYSLIB1054
+ true
+ true
@@ -27,7 +29,7 @@
-
+
diff --git a/src/DxFeed.Graal.Net/Ipf/InstrumentProfile.cs b/src/DxFeed.Graal.Net/Ipf/InstrumentProfile.cs
index d65d42f9..1a88d18d 100644
--- a/src/DxFeed.Graal.Net/Ipf/InstrumentProfile.cs
+++ b/src/DxFeed.Graal.Net/Ipf/InstrumentProfile.cs
@@ -1,13 +1,18 @@
//
-// Copyright © 2022 Devexperts LLC. All rights reserved.
+// Copyright © 2025 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
+using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using DxFeed.Graal.Net.Native.Ipf;
using DxFeed.Graal.Net.Utils;
+// Disable auto-property
+#pragma warning disable S2292
+
namespace DxFeed.Graal.Net.Ipf;
///
@@ -17,13 +22,46 @@ namespace DxFeed.Graal.Net.Ipf;
///
public class InstrumentProfile
{
- private readonly InstrumentProfileHandle handle;
+ private InstrumentProfileCustomFieldHandle customFieldHandle = InstrumentProfileCustomFieldHandle.Create();
+
+ private string type = string.Empty;
+ private string symbol = string.Empty;
+ private string description = string.Empty;
+ private string localSymbol = string.Empty;
+ private string localDescription = string.Empty;
+ private string country = string.Empty;
+ private string opol = string.Empty;
+ private string exchangeData = string.Empty;
+ private string exchanges = string.Empty;
+ private string currency = string.Empty;
+ private string baseCurrency = string.Empty;
+ private string cfi = string.Empty;
+ private string isin = string.Empty;
+ private string sedol = string.Empty;
+ private string cusip = string.Empty;
+ private int icb;
+ private int sic;
+ private double multiplier;
+ private string product = string.Empty;
+ private string underlying = string.Empty;
+ private double spc;
+ private string additionalUnderlyings = string.Empty;
+ private string mmy = string.Empty;
+ private int expiration;
+ private int lastTrade;
+ private double strike;
+ private string optionType = string.Empty;
+ private string expirationStyle = string.Empty;
+ private string settlementStyle = string.Empty;
+ private string priceIncrements = string.Empty;
+ private string tradingHours = string.Empty;
///
/// Initializes a new instance of the class.
///
- public InstrumentProfile() =>
- handle = InstrumentProfileHandle.Create();
+ public InstrumentProfile()
+ {
+ }
///
/// Initializes a new instance of the class,
@@ -36,11 +74,41 @@ public InstrumentProfile() =>
/// It performs a deep copy, ensuring that the new instance does not share references with the original,
/// making it safe from modifications to the original instance.
///
- public InstrumentProfile(InstrumentProfile ip) =>
- handle = InstrumentProfileHandle.Create(ip.GetHandle());
-
- internal InstrumentProfile(InstrumentProfileHandle handle) =>
- this.handle = handle;
+ public InstrumentProfile(InstrumentProfile ip)
+ {
+ type = ip.type;
+ symbol = ip.symbol;
+ description = ip.description;
+ localSymbol = ip.localSymbol;
+ localDescription = ip.localDescription;
+ country = ip.country;
+ opol = ip.opol;
+ exchangeData = ip.exchangeData;
+ exchanges = ip.exchanges;
+ currency = ip.currency;
+ baseCurrency = ip.baseCurrency;
+ cfi = ip.cfi;
+ isin = ip.isin;
+ sedol = ip.sedol;
+ cusip = ip.cusip;
+ icb = ip.icb;
+ sic = ip.sic;
+ multiplier = ip.multiplier;
+ product = ip.product;
+ underlying = ip.underlying;
+ spc = ip.spc;
+ additionalUnderlyings = ip.additionalUnderlyings;
+ mmy = ip.mmy;
+ expiration = ip.expiration;
+ lastTrade = ip.lastTrade;
+ strike = ip.strike;
+ optionType = ip.optionType;
+ expirationStyle = ip.expirationStyle;
+ settlementStyle = ip.settlementStyle;
+ priceIncrements = ip.priceIncrements;
+ tradingHours = ip.tradingHours;
+ customFieldHandle = InstrumentProfileCustomFieldHandle.Create(ip.customFieldHandle);
+ }
///
/// Gets or sets type of instrument.
@@ -50,8 +118,8 @@ internal InstrumentProfile(InstrumentProfileHandle handle) =>
/// "STOCK", "FUTURE", "OPTION".
public string Type
{
- get => handle.Type;
- set => handle.Type = value;
+ get => type;
+ set => type = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -62,8 +130,8 @@ public string Type
/// "GOOG", "/YGM9", ".ZYEAD".
public string Symbol
{
- get => handle.Symbol;
- set => handle.Symbol = value;
+ get => symbol;
+ set => symbol = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -73,8 +141,8 @@ public string Symbol
/// "Google Inc.", "Mini Gold Futures,Jun-2009,ETH".
public string Description
{
- get => handle.Description;
- set => handle.Description = value;
+ get => description;
+ set => description = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -83,8 +151,8 @@ public string Description
///
public string LocalSymbol
{
- get => handle.LocalSymbol;
- set => handle.LocalSymbol = value;
+ get => localSymbol;
+ set => localSymbol = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -93,8 +161,8 @@ public string LocalSymbol
///
public string LocalDescription
{
- get => handle.LocalDescription;
- set => handle.LocalDescription = value;
+ get => localDescription;
+ set => localDescription = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -105,8 +173,8 @@ public string LocalDescription
/// "US", "RU".
public string Country
{
- get => handle.Country;
- set => handle.Country = value;
+ get => country;
+ set => country = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -119,8 +187,8 @@ public string Country
/// "XNAS", "RTSX".
public string OPOL
{
- get => handle.OPOL;
- set => handle.OPOL = value;
+ get => opol;
+ set => opol = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -129,8 +197,8 @@ public string OPOL
///
public string ExchangeData
{
- get => handle.ExchangeData;
- set => handle.ExchangeData = value;
+ get => exchangeData;
+ set => exchangeData = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -145,8 +213,8 @@ public string ExchangeData
/// "ARCX;CBSX;XNAS;XNYS".
public string Exchanges
{
- get => handle.Exchanges;
- set => handle.Exchanges = value;
+ get => exchanges;
+ set => exchanges = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -157,8 +225,8 @@ public string Exchanges
/// "USD", "RUB".
public string Currency
{
- get => handle.Currency;
- set => handle.Currency = value;
+ get => currency;
+ set => currency = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -167,8 +235,8 @@ public string Currency
///
public string BaseCurrency
{
- get => handle.BaseCurrency;
- set => handle.BaseCurrency = value;
+ get => baseCurrency;
+ set => baseCurrency = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -182,8 +250,8 @@ public string BaseCurrency
/// "ESNTPB", "ESXXXX", "ES", "OPASPS".
public string CFI
{
- get => handle.CFI;
- set => handle.CFI = value;
+ get => cfi;
+ set => cfi = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -195,8 +263,8 @@ public string CFI
/// "DE0007100000", "US38259P5089".
public string ISIN
{
- get => handle.ISIN;
- set => handle.ISIN = value;
+ get => isin;
+ set => isin = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -208,8 +276,8 @@ public string ISIN
/// "2310967", "5766857".
public string SEDOL
{
- get => handle.SEDOL;
- set => handle.SEDOL = value;
+ get => sedol;
+ set => sedol = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -220,8 +288,8 @@ public string SEDOL
/// "38259P508".
public string CUSIP
{
- get => handle.CUSIP;
- set => handle.CUSIP = value;
+ get => cusip;
+ set => cusip = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -233,8 +301,8 @@ public string CUSIP
/// "9535".
public int ICB
{
- get => handle.ICB;
- set => handle.ICB = value;
+ get => icb;
+ set => icb = value;
}
///
@@ -246,8 +314,8 @@ public int ICB
/// "7371".
public int SIC
{
- get => handle.SIC;
- set => handle.SIC = value;
+ get => sic;
+ set => sic = value;
}
///
@@ -256,8 +324,8 @@ public int SIC
/// "100", "33.2".
public double Multiplier
{
- get => handle.Multiplier;
- set => handle.Multiplier = value;
+ get => multiplier;
+ set => multiplier = value;
}
///
@@ -266,8 +334,8 @@ public double Multiplier
/// "/YG".
public string Product
{
- get => handle.Product;
- set => handle.Product = value;
+ get => product;
+ set => product = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -276,8 +344,8 @@ public string Product
/// "C", "/YGM9".
public string Underlying
{
- get => handle.Underlying;
- set => handle.Underlying = value;
+ get => underlying;
+ set => underlying = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -286,8 +354,8 @@ public string Underlying
/// "1", "100".
public double SPC
{
- get => handle.SPC;
- set => handle.SPC = value;
+ get => spc;
+ set => spc = value;
}
///
@@ -303,8 +371,8 @@ public double SPC
/// "SE 50", "FIS 53; US$ 45.46".
public string AdditionalUnderlyings
{
- get => handle.AdditionalUnderlyings;
- set => handle.AdditionalUnderlyings = value;
+ get => additionalUnderlyings;
+ set => additionalUnderlyings = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -318,8 +386,8 @@ public string AdditionalUnderlyings
///
public string MMY
{
- get => handle.MMY;
- set => handle.MMY = value;
+ get => mmy;
+ set => mmy = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -328,8 +396,8 @@ public string MMY
/// DayUtil.GetYearMonthDayByDayId(20090117).
public int Expiration
{
- get => handle.Expiration;
- set => handle.Expiration = value;
+ get => expiration;
+ set => expiration = value;
}
///
@@ -338,8 +406,8 @@ public int Expiration
/// DayUtil.GetYearMonthDayByDayId(20090117).
public int LastTrade
{
- get => handle.LastTrade;
- set => handle.LastTrade = value;
+ get => lastTrade;
+ set => lastTrade = value;
}
///
@@ -348,8 +416,8 @@ public int LastTrade
/// "80", "22.5".
public double Strike
{
- get => handle.Strike;
- set => handle.Strike = value;
+ get => strike;
+ set => strike = value;
}
///
@@ -367,8 +435,8 @@ public double Strike
///
public string OptionType
{
- get => handle.OptionType;
- set => handle.OptionType = value;
+ get => optionType;
+ set => optionType = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -376,8 +444,8 @@ public string OptionType
///
public string ExpirationStyle
{
- get => handle.ExpirationStyle;
- set => handle.ExpirationStyle = value;
+ get => expirationStyle;
+ set => expirationStyle = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -385,8 +453,8 @@ public string ExpirationStyle
///
public string SettlementStyle
{
- get => handle.SettlementStyle;
- set => handle.SettlementStyle = value;
+ get => settlementStyle;
+ set => settlementStyle = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -402,8 +470,8 @@ public string SettlementStyle
/// "0.25", "0.01 3; 0.05".
public string PriceIncrements
{
- get => handle.PriceIncrements;
- set => handle.PriceIncrements = value;
+ get => priceIncrements;
+ set => priceIncrements = string.IsNullOrEmpty(value) ? string.Empty : value;
}
///
@@ -412,8 +480,14 @@ public string PriceIncrements
///
public string TradingHours
{
- get => handle.TradingHours;
- set => handle.TradingHours = value;
+ get => tradingHours;
+ set => tradingHours = string.IsNullOrEmpty(value) ? string.Empty : value;
+ }
+
+ internal InstrumentProfileCustomFieldHandle CustomFields
+ {
+ get => customFieldHandle;
+ set => customFieldHandle = value;
}
///
@@ -422,7 +496,7 @@ public string TradingHours
/// The name of the field.
/// The field value, or an empty string if the field does not exist.
public string GetField(string name) =>
- handle.GetField(name);
+ customFieldHandle.GetField(name);
///
/// Sets the value of the field with the specified name.
@@ -430,7 +504,7 @@ public string GetField(string name) =>
/// The name of the field.
/// The value to set for the field.
public void SetField(string name, string value) =>
- handle.SetField(name, value);
+ customFieldHandle.SetField(name, value);
///
/// Gets the numeric value of the field with the specified name.
@@ -438,7 +512,7 @@ public void SetField(string name, string value) =>
/// The name of the field.
/// The numeric field value.
public double GetNumericField(string name) =>
- handle.GetNumericField(name);
+ customFieldHandle.GetNumericField(name);
///
/// Sets the numeric value of the field with the specified name.
@@ -446,7 +520,7 @@ public double GetNumericField(string name) =>
/// The name of the field.
/// The numeric value to set for the field.
public void SetNumericField(string name, double value) =>
- handle.SetNumericField(name, value);
+ customFieldHandle.SetNumericField(name, value);
///
/// Gets the day id value of the date field with the specified name.
@@ -455,7 +529,7 @@ public void SetNumericField(string name, double value) =>
/// The name of the date field.
/// The day id field value.
public int GetDateField(string name) =>
- handle.GetDateField(name);
+ customFieldHandle.GetDateField(name);
///
/// Sets the day id value of the date field with the specified name.
@@ -464,7 +538,7 @@ public int GetDateField(string name) =>
/// The name of the date field.
/// The day id value to set for the date field.
public void SetDateField(string name, int value) =>
- handle.SetDateField(name, value);
+ customFieldHandle.SetDateField(name, value);
///
/// Adds names of non-empty custom fields to the specified collection.
@@ -476,30 +550,232 @@ public void SetDateField(string name, int value) =>
/// true if changed as a result of the call; otherwise, false.
///
public bool AddNonEmptyCustomFieldNames(ICollection targetFieldNames) =>
- handle.AddNonEmptyCustomFieldNames(targetFieldNames);
+ customFieldHandle.AddNonEmptyCustomFieldNames(targetFieldNames);
///
/// Determines whether the specified object is equal to the current object.
///
/// The object to compare with the current object.
/// true if the specified object is equal to the current object; otherwise, false.
- public override bool Equals(object? obj) =>
- obj is InstrumentProfile ip && handle.Equals(ip.GetHandle());
+ public override bool Equals(object? obj)
+ {
+ if (ReferenceEquals(this, obj))
+ {
+ return true;
+ }
+
+ if (obj is not InstrumentProfile that)
+ {
+ return false;
+ }
+
+ if (!type.Equals(that.type, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!symbol.Equals(that.symbol, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!description.Equals(that.description, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!localSymbol.Equals(that.localSymbol, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!localDescription.Equals(that.localDescription, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!country.Equals(that.country, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!opol.Equals(that.opol, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!exchangeData.Equals(that.exchangeData, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!exchanges.Equals(that.exchanges, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!currency.Equals(that.currency, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!baseCurrency.Equals(that.baseCurrency, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!cfi.Equals(that.cfi, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!isin.Equals(that.isin, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!sedol.Equals(that.sedol, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!cusip.Equals(that.cusip, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (icb != that.icb)
+ {
+ return false;
+ }
+
+ if (sic != that.sic)
+ {
+ return false;
+ }
+
+ if (!multiplier.Equals(that.multiplier))
+ {
+ return false;
+ }
+
+ if (!product.Equals(that.product, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!underlying.Equals(that.underlying, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!spc.Equals(that.spc))
+ {
+ return false;
+ }
+
+ if (!additionalUnderlyings.Equals(that.additionalUnderlyings, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!mmy.Equals(that.mmy, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (expiration != that.expiration)
+ {
+ return false;
+ }
+
+ if (lastTrade != that.lastTrade)
+ {
+ return false;
+ }
+
+ if (!strike.Equals(that.Strike))
+ {
+ return false;
+ }
+
+ if (!optionType.Equals(that.optionType, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!expirationStyle.Equals(that.expirationStyle, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!settlementStyle.Equals(that.settlementStyle, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!priceIncrements.Equals(that.priceIncrements, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ if (!tradingHours.Equals(that.tradingHours, StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ return customFieldHandle.Equals(that.customFieldHandle);
+ }
///
/// Returns a hash code value for this object.
///
/// A hash code value for this object.
- public override int GetHashCode() =>
- handle.GetHashCode();
+ [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode", Justification = "Not immutable")]
+ public override int GetHashCode()
+ {
+ var result = type.GetHashCode();
+ result = (31 * result) + symbol.GetHashCode();
+ result = (31 * result) + description.GetHashCode();
+ result = (31 * result) + localSymbol.GetHashCode();
+ result = (31 * result) + localDescription.GetHashCode();
+ result = (31 * result) + country.GetHashCode();
+ result = (31 * result) + opol.GetHashCode();
+ result = (31 * result) + exchangeData.GetHashCode();
+ result = (31 * result) + exchanges.GetHashCode();
+ result = (31 * result) + currency.GetHashCode();
+ result = (31 * result) + baseCurrency.GetHashCode();
+ result = (31 * result) + cfi.GetHashCode();
+ result = (31 * result) + isin.GetHashCode();
+ result = (31 * result) + sedol.GetHashCode();
+ result = (31 * result) + cusip.GetHashCode();
+ result = (31 * result) + icb;
+ result = (31 * result) + sic;
+ var temp = BitConverter.DoubleToInt64Bits(multiplier);
+ result = (31 * result) + (int)(temp ^ (long)((ulong)temp >> 32));
+ result = (31 * result) + product.GetHashCode();
+ result = (31 * result) + underlying.GetHashCode();
+ temp = BitConverter.DoubleToInt64Bits(spc);
+ result = (31 * result) + (int)(temp ^ (long)((ulong)temp >> 32));
+ result = (31 * result) + additionalUnderlyings.GetHashCode();
+ result = (31 * result) + mmy.GetHashCode();
+ result = (31 * result) + expiration;
+ result = (31 * result) + lastTrade;
+ temp = BitConverter.DoubleToInt64Bits(strike);
+ result = (31 * result) + (int)(temp ^ (long)((ulong)temp >> 32));
+ result = (31 * result) + optionType.GetHashCode();
+ result = (31 * result) + expirationStyle.GetHashCode();
+ result = (31 * result) + settlementStyle.GetHashCode();
+ result = (31 * result) + priceIncrements.GetHashCode();
+ result = (31 * result) + tradingHours.GetHashCode();
+ result = (31 * result) + customFieldHandle.GetHashCode();
+ return result;
+ }
///
/// Returns a string representation of the instrument profile.
///
/// The string representation.
public override string ToString() =>
- handle.ToString();
-
- internal InstrumentProfileHandle GetHandle() =>
- handle;
+ $"{Type} {Symbol}";
}
diff --git a/src/DxFeed.Graal.Net/Native/Interop/InstrumentProfileMarshaler.cs b/src/DxFeed.Graal.Net/Native/Interop/InstrumentProfileMarshaler.cs
new file mode 100644
index 00000000..1109fa83
--- /dev/null
+++ b/src/DxFeed.Graal.Net/Native/Interop/InstrumentProfileMarshaler.cs
@@ -0,0 +1,169 @@
+//
+// Copyright © 2025 Devexperts LLC. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+
+using System;
+using System.Runtime.InteropServices;
+using DxFeed.Graal.Net.Ipf;
+using DxFeed.Graal.Net.Native.Graal;
+using DxFeed.Graal.Net.Native.Ipf;
+using static DxFeed.Graal.Net.Native.ErrorHandling.ErrorCheck;
+
+namespace DxFeed.Graal.Net.Native.Interop;
+
+internal sealed class InstrumentProfileMarshaler : AbstractMarshaler
+{
+ private static readonly Lazy Instance = new();
+
+ public static ICustomMarshaler GetInstance(string cookie) =>
+ Instance.Value;
+
+ public override unsafe object? ConvertNativeToManaged(IntPtr native)
+ {
+ if (native == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ var profile = (InstrumentProfileNative*)native;
+ return new InstrumentProfile
+ {
+ Type = profile->Type!,
+ Symbol = profile->Symbol!,
+ Description = profile->Description!,
+ LocalSymbol = profile->LocalSymbol!,
+ LocalDescription = profile->LocalDescription!,
+ Country = profile->Country!,
+ OPOL = profile->OPOL!,
+ ExchangeData = profile->ExchangeData!,
+ Exchanges = profile->Exchanges!,
+ Currency = profile->Currency!,
+ BaseCurrency = profile->BaseCurrency!,
+ CFI = profile->CFI!,
+ ISIN = profile->ISIN!,
+ SEDOL = profile->SEDOL!,
+ CUSIP = profile->CUSIP!,
+ ICB = profile->ICB,
+ SIC = profile->SIC,
+ Multiplier = profile->Multiplier,
+ Product = profile->Product!,
+ Underlying = profile->Underlying!,
+ SPC = profile->SPC,
+ AdditionalUnderlyings = profile->AdditionalUnderlyings!,
+ MMY = profile->MMY!,
+ Expiration = profile->Expiration,
+ LastTrade = profile->LastTrade,
+ Strike = profile->Strike,
+ OptionType = profile->OptionType!,
+ ExpirationStyle = profile->ExpirationStyle!,
+ SettlementStyle = profile->SettlementStyle!,
+ PriceIncrements = profile->PriceIncrements!,
+ TradingHours = profile->TradingHours!,
+ CustomFields = profile->CustomFields != IntPtr.Zero ?
+ InstrumentProfileCustomFieldHandle.Clone(profile->CustomFields) :
+ InstrumentProfileCustomFieldHandle.Create(),
+ };
+ }
+
+ public override unsafe IntPtr ConvertManagedToNative(object? managed)
+ {
+ if (managed is not InstrumentProfile profile)
+ {
+ throw new ArgumentException("Managed object must be a InstrumentProfile.", nameof(managed));
+ }
+
+ var ptr = (InstrumentProfileNative*)Marshal.AllocHGlobal(sizeof(InstrumentProfileNative));
+ *ptr = new InstrumentProfileNative
+ {
+ Type = profile.Type,
+ Symbol = profile.Symbol,
+ Description = profile.Description,
+ LocalSymbol = profile.LocalSymbol,
+ LocalDescription = profile.LocalDescription,
+ Country = profile.Country,
+ OPOL = profile.OPOL,
+ ExchangeData = profile.ExchangeData,
+ Exchanges = profile.Exchanges,
+ Currency = profile.Currency,
+ BaseCurrency = profile.BaseCurrency,
+ CFI = profile.CFI,
+ ISIN = profile.ISIN,
+ SEDOL = profile.SEDOL,
+ CUSIP = profile.CUSIP,
+ ICB = profile.ICB,
+ SIC = profile.SIC,
+ Multiplier = profile.Multiplier,
+ Product = profile.Product,
+ Underlying = profile.Underlying,
+ SPC = profile.SPC,
+ AdditionalUnderlyings = profile.AdditionalUnderlyings,
+ MMY = profile.MMY,
+ Expiration = profile.Expiration,
+ LastTrade = profile.LastTrade,
+ Strike = profile.Strike,
+ OptionType = profile.OptionType,
+ ExpirationStyle = profile.ExpirationStyle,
+ SettlementStyle = profile.SettlementStyle,
+ PriceIncrements = profile.PriceIncrements,
+ TradingHours = profile.TradingHours,
+ CustomFields = IntPtr.Zero,
+ Hash = 0,
+ };
+ return (IntPtr)ptr;
+ }
+
+ public override unsafe void CleanUpFromManaged(IntPtr ptr)
+ {
+ var profile = (InstrumentProfileNative*)ptr;
+ profile->Type.Release();
+ profile->Symbol.Release();
+ profile->Description.Release();
+ profile->LocalSymbol.Release();
+ profile->LocalDescription.Release();
+ profile->Country.Release();
+ profile->OPOL.Release();
+ profile->ExchangeData.Release();
+ profile->Exchanges.Release();
+ profile->Currency.Release();
+ profile->BaseCurrency.Release();
+ profile->CFI.Release();
+ profile->ISIN.Release();
+ profile->SEDOL.Release();
+ profile->CUSIP.Release();
+ profile->Product.Release();
+ profile->Underlying.Release();
+ profile->AdditionalUnderlyings.Release();
+ profile->MMY.Release();
+ profile->OptionType.Release();
+ profile->ExpirationStyle.Release();
+ profile->SettlementStyle.Release();
+ profile->PriceIncrements.Release();
+ profile->TradingHours.Release();
+ Marshal.FreeHGlobal((IntPtr)profile);
+ }
+
+ public override void CleanUpFromNative(IntPtr ptr) =>
+ SafeCall(Import.Release(Isolate.CurrentThread, ptr));
+
+ public override void CleanUpListFromNative(IntPtr ptr) =>
+ SafeCall(Import.ReleaseList(Isolate.CurrentThread, ptr));
+
+ private static class Import
+ {
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ EntryPoint = "dxfg_instrument_profile_free")]
+ public static extern int Release(nint thread, nint handle);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ EntryPoint = "dxfg_instrument_profile2_list_free")]
+ public static extern int ReleaseList(nint thread, nint handle);
+ }
+}
diff --git a/src/DxFeed.Graal.Net/Native/Interop/JavaHandle.cs b/src/DxFeed.Graal.Net/Native/Interop/JavaHandle.cs
index 8bdddf3a..a6a7c325 100644
--- a/src/DxFeed.Graal.Net/Native/Interop/JavaHandle.cs
+++ b/src/DxFeed.Graal.Net/Native/Interop/JavaHandle.cs
@@ -1,5 +1,5 @@
//
-// Copyright © 2024 Devexperts LLC. All rights reserved.
+// Copyright © 2025 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
@@ -78,7 +78,7 @@ public override bool Equals(object? obj)
return false;
}
- return Import.Equals(CurrentThread, this, that) != 0;
+ return ErrorCheck.SafeCall(Import.Equals(CurrentThread, this, that)) != 0;
}
public override string ToString() =>
diff --git a/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileCollectorHandle.cs b/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileCollectorHandle.cs
index 9a4baed5..3b2f13d7 100644
--- a/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileCollectorHandle.cs
+++ b/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileCollectorHandle.cs
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Devexperts LLC. All rights reserved.
+// Copyright © 2025 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
@@ -26,7 +26,7 @@ public long GetLastUpdateTime() =>
ErrorCheck.SafeCall(NativeGetLastUpdateTime(CurrentThread, this));
public void UpdateInstrumentProfile(InstrumentProfile ip) =>
- ErrorCheck.SafeCall(NativeUpdateInstrumentProfile(CurrentThread, this, ip.GetHandle()));
+ ErrorCheck.SafeCall(NativeUpdateInstrumentProfile(CurrentThread, this, ip));
public IEnumerable View()
{
@@ -74,11 +74,12 @@ private static extern long NativeGetLastUpdateTime(
ImportInfo.DllName,
CallingConvention = CallingConvention.Cdecl,
CharSet = CharSet.Ansi,
- EntryPoint = "dxfg_InstrumentProfileCollector_updateInstrumentProfile")]
+ EntryPoint = "dxfg_InstrumentProfileCollector_updateInstrumentProfile2")]
private static extern int NativeUpdateInstrumentProfile(
nint thread,
InstrumentProfileCollectorHandle collector,
- InstrumentProfileHandle ip);
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(InstrumentProfileMarshaler))]
+ InstrumentProfile ip);
[DllImport(
ImportInfo.DllName,
diff --git a/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileCustomFieldHandle.cs b/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileCustomFieldHandle.cs
new file mode 100644
index 00000000..b8c3ee5b
--- /dev/null
+++ b/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileCustomFieldHandle.cs
@@ -0,0 +1,267 @@
+//
+// Copyright © 2025 Devexperts LLC. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using DxFeed.Graal.Net.Native.Interop;
+using static DxFeed.Graal.Net.Native.ErrorHandling.ErrorCheck;
+
+namespace DxFeed.Graal.Net.Native.Ipf;
+
+internal class InstrumentProfileCustomFieldHandle : JavaHandle
+{
+ private static readonly StringMarshaler _marshaler = new();
+
+ public static InstrumentProfileCustomFieldHandle Create()
+ {
+ SafeCall(Import.New(CurrentThread, out var handle));
+ return handle;
+ }
+
+ public static InstrumentProfileCustomFieldHandle Create(InstrumentProfileCustomFieldHandle handle)
+ {
+ SafeCall(Import.New(CurrentThread, handle, out var newHandle));
+ return newHandle;
+ }
+
+ public static InstrumentProfileCustomFieldHandle Clone(IntPtr handle)
+ {
+ SafeCall(Import.CloneHandle(CurrentThread, handle, out var newHandle));
+ return newHandle;
+ }
+
+ public string GetField(string name)
+ {
+ SafeCall(Import.GetField(CurrentThread, this, name, out var value));
+ return value;
+ }
+
+ public void SetField(string name, string value) =>
+ SafeCall(Import.SetField(CurrentThread, this, name, value));
+
+ public double GetNumericField(string name)
+ {
+ SafeCall(Import.GetNumericField(CurrentThread, this, name, out var value));
+ return value;
+ }
+
+ public void SetNumericField(string name, double value) =>
+ SafeCall(Import.SetNumericField(CurrentThread, this, name, value));
+
+ public int GetDateField(string name)
+ {
+ SafeCall(Import.GetDateField(CurrentThread, this, name, out var value));
+ return value;
+ }
+
+ public void SetDateField(string name, int value) =>
+ SafeCall(Import.SetDateField(CurrentThread, this, name, value));
+
+ public unsafe bool AddNonEmptyCustomFieldNames(ICollection targetFieldNames)
+ {
+ SafeCall(Import.GetNonEmptyFieldsNames(CurrentThread, this, out var ptr));
+ var fields = ConvertToStringList(ptr);
+
+ if (fields.Count == 0)
+ {
+ return false;
+ }
+
+ if (targetFieldNames is ISet set)
+ {
+ var updated = false;
+ foreach (var field in fields)
+ {
+ if (set.Add(field))
+ {
+ updated = true;
+ }
+ }
+
+ return updated;
+ }
+
+ foreach (var field in fields)
+ {
+ targetFieldNames.Add(field);
+ }
+
+ return true;
+ }
+
+ private static unsafe List ConvertToStringList(ListNative* handles)
+ {
+ try
+ {
+ var venues = new List(handles->Size);
+ for (var i = 0; i < handles->Size; i++)
+ {
+ var profile = (string)_marshaler.ConvertNativeToManaged((IntPtr)handles->Elements[i])!;
+ venues.Add(profile);
+ }
+
+ return venues;
+ }
+ finally
+ {
+ SafeCall(Import.ReleaseList(CurrentThread, (IntPtr)handles));
+ }
+ }
+
+ private static class Import
+ {
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ ExactSpelling = true,
+ BestFitMapping = false,
+ ThrowOnUnmappableChar = true,
+ EntryPoint = "dxfg_InstrumentProfileCustomFields_new")]
+ public static extern int New(
+ nint thread,
+ out InstrumentProfileCustomFieldHandle handle);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ ExactSpelling = true,
+ BestFitMapping = false,
+ ThrowOnUnmappableChar = true,
+ EntryPoint = "dxfg_InstrumentProfileCustomFields_new3")]
+ public static extern int New(
+ nint thread,
+ InstrumentProfileCustomFieldHandle handle,
+ out InstrumentProfileCustomFieldHandle newHandle);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ ExactSpelling = true,
+ BestFitMapping = false,
+ ThrowOnUnmappableChar = true,
+ EntryPoint = "dxfg_InstrumentProfileCustomFields_getField")]
+ public static extern int GetField(
+ nint thread,
+ InstrumentProfileCustomFieldHandle handle,
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
+ string name,
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
+ out string value);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ ExactSpelling = true,
+ BestFitMapping = false,
+ ThrowOnUnmappableChar = true,
+ EntryPoint = "dxfg_InstrumentProfileCustomFields_setField")]
+ public static extern int SetField(
+ nint thread,
+ InstrumentProfileCustomFieldHandle handle,
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
+ string name,
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
+ string value);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ ExactSpelling = true,
+ BestFitMapping = false,
+ ThrowOnUnmappableChar = true,
+ EntryPoint = "dxfg_InstrumentProfileCustomFields_getNumericField")]
+ public static extern int GetNumericField(
+ nint thread,
+ InstrumentProfileCustomFieldHandle handle,
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
+ string name,
+ out double value);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ ExactSpelling = true,
+ BestFitMapping = false,
+ ThrowOnUnmappableChar = true,
+ EntryPoint = "dxfg_InstrumentProfileCustomFields_setNumericField")]
+ public static extern int SetNumericField(
+ nint thread,
+ InstrumentProfileCustomFieldHandle handle,
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
+ string name,
+ double value);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ ExactSpelling = true,
+ BestFitMapping = false,
+ ThrowOnUnmappableChar = true,
+ EntryPoint = "dxfg_InstrumentProfileCustomFields_getDateField")]
+ public static extern int GetDateField(
+ nint thread,
+ InstrumentProfileCustomFieldHandle handle,
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
+ string name,
+ out int value);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ ExactSpelling = true,
+ BestFitMapping = false,
+ ThrowOnUnmappableChar = true,
+ EntryPoint = "dxfg_InstrumentProfileCustomFields_setDateField")]
+ public static extern int SetDateField(
+ nint thread,
+ InstrumentProfileCustomFieldHandle handle,
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
+ string name,
+ int value);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ ExactSpelling = true,
+ BestFitMapping = false,
+ ThrowOnUnmappableChar = true,
+ EntryPoint = "dxfg_InstrumentProfileCustomFields_getNonEmptyFieldNames")]
+ public static extern unsafe int GetNonEmptyFieldsNames(
+ nint thread,
+ InstrumentProfileCustomFieldHandle handle,
+ out ListNative* fieldNames);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ ExactSpelling = true,
+ BestFitMapping = false,
+ ThrowOnUnmappableChar = true,
+ EntryPoint = "dxfg_JavaObjectHandler_clone")]
+ public static extern int CloneHandle(
+ nint thread,
+ IntPtr handle,
+ out InstrumentProfileCustomFieldHandle newHandle);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ EntryPoint = "dxfg_CList_String_release")]
+ public static extern int ReleaseList(nint thread, nint handle);
+ }
+}
diff --git a/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileHandle.cs b/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileHandle.cs
deleted file mode 100644
index a01423e3..00000000
--- a/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileHandle.cs
+++ /dev/null
@@ -1,1106 +0,0 @@
-//
-// Copyright © 2024 Devexperts LLC. All rights reserved.
-// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
-// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using DxFeed.Graal.Net.Ipf;
-using DxFeed.Graal.Net.Native.Interop;
-using static DxFeed.Graal.Net.Native.ErrorHandling.ErrorCheck;
-
-namespace DxFeed.Graal.Net.Native.Ipf;
-
-internal class InstrumentProfileHandle : JavaHandle
-{
- public InstrumentProfileHandle()
- {
- }
-
- public InstrumentProfileHandle(IntPtr handle)
- : base(handle)
- {
- }
-
- public string Type
- {
- get => SafeCall(Import.GetType(CurrentThread, this));
- set => SafeCall(Import.SetType(CurrentThread, this, value));
- }
-
- public string Symbol
- {
- get => SafeCall(Import.GetSymbol(CurrentThread, this));
- set => SafeCall(Import.SetSymbol(CurrentThread, this, value));
- }
-
- public string Description
- {
- get => SafeCall(Import.GetDescription(CurrentThread, this));
- set => SafeCall(Import.SetDescription(CurrentThread, this, value));
- }
-
- public string LocalSymbol
- {
- get => SafeCall(Import.GetLocalSymbol(CurrentThread, this));
- set => SafeCall(Import.SetLocalSymbol(CurrentThread, this, value));
- }
-
- public string LocalDescription
- {
- get => SafeCall(Import.GetLocalDescription(CurrentThread, this));
- set => SafeCall(Import.SetLocalDescription(CurrentThread, this, value));
- }
-
- public string Country
- {
- get => SafeCall(Import.GetCountry(CurrentThread, this));
- set => SafeCall(Import.SetCountry(CurrentThread, this, value));
- }
-
- public string OPOL
- {
- get => SafeCall(Import.GetOPOL(CurrentThread, this));
- set => SafeCall(Import.SetOPOL(CurrentThread, this, value));
- }
-
- public string ExchangeData
- {
- get => SafeCall(Import.GetExchangeData(CurrentThread, this));
- set => SafeCall(Import.SetExchangeData(CurrentThread, this, value));
- }
-
- public string Exchanges
- {
- get => SafeCall(Import.GetExchanges(CurrentThread, this));
- set => SafeCall(Import.SetExchanges(CurrentThread, this, value));
- }
-
- public string Currency
- {
- get => SafeCall(Import.GetCurrency(CurrentThread, this));
- set => SafeCall(Import.SetCurrency(CurrentThread, this, value));
- }
-
- public string BaseCurrency
- {
- get => SafeCall(Import.GetBaseCurrency(CurrentThread, this));
- set => SafeCall(Import.SetBaseCurrency(CurrentThread, this, value));
- }
-
- public string CFI
- {
- get => SafeCall(Import.GetCFI(CurrentThread, this));
- set => SafeCall(Import.SetCFI(CurrentThread, this, value));
- }
-
- public string ISIN
- {
- get => SafeCall(Import.GetISIN(CurrentThread, this));
- set => SafeCall(Import.SetISIN(CurrentThread, this, value));
- }
-
- public string SEDOL
- {
- get => SafeCall(Import.GetSEDOL(CurrentThread, this));
- set => SafeCall(Import.SetSEDOL(CurrentThread, this, value));
- }
-
- public string CUSIP
- {
- get => SafeCall(Import.GetCUSIP(CurrentThread, this));
- set => SafeCall(Import.SetCUSIP(CurrentThread, this, value));
- }
-
- public int ICB
- {
- get => SafeCall(Import.GetICB(CurrentThread, this));
- set => SafeCall(Import.SetICB(CurrentThread, this, value));
- }
-
- public int SIC
- {
- get => SafeCall(Import.GetSIC(CurrentThread, this));
- set => SafeCall(Import.SetSIC(CurrentThread, this, value));
- }
-
- public double Multiplier
- {
- get => SafeCall(Import.GetMultiplier(CurrentThread, this));
- set => SafeCall(Import.SetMultiplier(CurrentThread, this, value));
- }
-
- public string Product
- {
- get => SafeCall(Import.GetProduct(CurrentThread, this));
- set => SafeCall(Import.SetProduct(CurrentThread, this, value));
- }
-
- public string Underlying
- {
- get => SafeCall(Import.GetUnderlying(CurrentThread, this));
- set => SafeCall(Import.SetUnderlying(CurrentThread, this, value));
- }
-
- public double SPC
- {
- get => SafeCall(Import.GetSPC(CurrentThread, this));
- set => SafeCall(Import.SetSPC(CurrentThread, this, value));
- }
-
- public string AdditionalUnderlyings
- {
- get => SafeCall(Import.GetAdditionalUnderlyings(CurrentThread, this));
- set => SafeCall(Import.SetAdditionalUnderlyings(CurrentThread, this, value));
- }
-
- public string MMY
- {
- get => SafeCall(Import.GetMMY(CurrentThread, this));
- set => SafeCall(Import.SetMMY(CurrentThread, this, value));
- }
-
- public int Expiration
- {
- get => SafeCall(Import.GetExpiration(CurrentThread, this));
- set => SafeCall(Import.SetExpiration(CurrentThread, this, value));
- }
-
- public int LastTrade
- {
- get => SafeCall(Import.GetLastTrade(CurrentThread, this));
- set => SafeCall(Import.SetLastTrade(CurrentThread, this, value));
- }
-
- public double Strike
- {
- get => SafeCall(Import.GetStrike(CurrentThread, this));
- set => SafeCall(Import.SetStrike(CurrentThread, this, value));
- }
-
- public string OptionType
- {
- get => SafeCall(Import.GetOptionType(CurrentThread, this));
- set => SafeCall(Import.SetOptionType(CurrentThread, this, value));
- }
-
- public string ExpirationStyle
- {
- get => SafeCall(Import.GetExpirationStyle(CurrentThread, this));
- set => SafeCall(Import.SetExpirationStyle(CurrentThread, this, value));
- }
-
- public string SettlementStyle
- {
- get => SafeCall(Import.GetSettlementStyle(CurrentThread, this));
- set => SafeCall(Import.SetSettlementStyle(CurrentThread, this, value));
- }
-
- public string PriceIncrements
- {
- get => SafeCall(Import.GetPriceIncrements(CurrentThread, this));
- set => SafeCall(Import.SetPriceIncrements(CurrentThread, this, value));
- }
-
- public string TradingHours
- {
- get => SafeCall(Import.GetTradingHours(CurrentThread, this));
- set => SafeCall(Import.SetTradingHours(CurrentThread, this, value));
- }
-
- public static InstrumentProfileHandle Create() =>
- SafeCall(Import.Create(CurrentThread));
-
- public static InstrumentProfileHandle Create(InstrumentProfileHandle handle) =>
- SafeCall(Import.Create(CurrentThread, handle));
-
- public string GetField(string name) =>
- SafeCall(Import.GetField(CurrentThread, this, name));
-
- public void SetField(string name, string value) =>
- SafeCall(Import.SetField(CurrentThread, this, name, value));
-
- public double GetNumericField(string name) =>
- SafeCall(Import.GetNumericField(CurrentThread, this, name));
-
- public void SetNumericField(string name, double value) =>
- SafeCall(Import.SetNumericField(CurrentThread, this, name, value));
-
- public int GetDateField(string name) =>
- SafeCall(Import.GetDateField(CurrentThread, this, name));
-
- public void SetDateField(string name, int value) =>
- SafeCall(Import.SetDateField(CurrentThread, this, name, value));
-
- public bool AddNonEmptyCustomFieldNames(ICollection targetFieldNames)
- {
- var fields = SafeCall(Import.GetNonEmptyCustomFieldNames(CurrentThread, this));
- foreach (var field in fields)
- {
- targetFieldNames.Add(field);
- }
-
- return fields.Count != 0;
- }
-
- private static class Import
- {
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- EntryPoint = "dxfg_InstrumentProfile_new")]
- public static extern InstrumentProfileHandle Create(nint thread);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- EntryPoint = "dxfg_InstrumentProfile_new2")]
- public static extern InstrumentProfileHandle Create(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getType")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetType(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setType")]
- public static extern int SetType(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getSymbol")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetSymbol(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setSymbol")]
- public static extern int SetSymbol(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getDescription")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetDescription(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setDescription")]
- public static extern int SetDescription(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getLocalSymbol")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetLocalSymbol(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setLocalSymbol")]
- public static extern int SetLocalSymbol(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getLocalDescription")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetLocalDescription(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setLocalDescription")]
- public static extern int SetLocalDescription(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getCountry")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetCountry(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setCountry")]
- public static extern int SetCountry(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getOPOL")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetOPOL(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setOPOL")]
- public static extern int SetOPOL(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getExchangeData")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetExchangeData(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setExchangeData")]
- public static extern int SetExchangeData(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getExchanges")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetExchanges(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setExchanges")]
- public static extern int SetExchanges(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getCurrency")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetCurrency(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setCurrency")]
- public static extern int SetCurrency(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getBaseCurrency")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetBaseCurrency(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setBaseCurrency")]
- public static extern int SetBaseCurrency(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getCFI")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetCFI(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setCFI")]
- public static extern int SetCFI(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getISIN")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetISIN(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setISIN")]
- public static extern int SetISIN(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getSEDOL")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetSEDOL(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setSEDOL")]
- public static extern int SetSEDOL(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getCUSIP")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetCUSIP(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setCUSIP")]
- public static extern int SetCUSIP(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getICB")]
- public static extern int GetICB(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setICB")]
- public static extern int SetICB(nint thread, InstrumentProfileHandle ip, int value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getSIC")]
- public static extern int GetSIC(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setSIC")]
- public static extern int SetSIC(nint thread, InstrumentProfileHandle ip, int value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getMultiplier")]
- public static extern double GetMultiplier(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setMultiplier")]
- public static extern int SetMultiplier(nint thread, InstrumentProfileHandle ip, double value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getProduct")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetProduct(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setProduct")]
- public static extern int SetProduct(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getUnderlying")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetUnderlying(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setUnderlying")]
- public static extern int SetUnderlying(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getSPC")]
- public static extern double GetSPC(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setSPC")]
- public static extern int SetSPC(nint thread, InstrumentProfileHandle ip, double value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getAdditionalUnderlyings")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetAdditionalUnderlyings(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setAdditionalUnderlyings")]
- public static extern int SetAdditionalUnderlyings(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getMMY")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetMMY(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setMMY")]
- public static extern int SetMMY(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getExpiration")]
- public static extern int GetExpiration(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setExpiration")]
- public static extern int SetExpiration(nint thread, InstrumentProfileHandle ip, int value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getLastTrade")]
- public static extern int GetLastTrade(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setLastTrade")]
- public static extern int SetLastTrade(nint thread, InstrumentProfileHandle ip, int value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getStrike")]
- public static extern double GetStrike(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setStrike")]
- public static extern int SetStrike(nint thread, InstrumentProfileHandle ip, double value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getOptionType")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetOptionType(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setOptionType")]
- public static extern int SetOptionType(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getExpirationStyle")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetExpirationStyle(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setExpirationStyle")]
- public static extern int SetExpirationStyle(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getSettlementStyle")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetSettlementStyle(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setSettlementStyle")]
- public static extern int SetSettlementStyle(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getPriceIncrements")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetPriceIncrements(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setPriceIncrements")]
- public static extern int SetPriceIncrements(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getTradingHours")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetTradingHours(nint thread, InstrumentProfileHandle ip);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setTradingHours")]
- public static extern int SetTradingHours(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getField")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- public static extern string GetField(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string name);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setField")]
- public static extern int SetField(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string name,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getNumericField")]
- public static extern double GetNumericField(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string name);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setNumericField")]
- public static extern int SetNumericField(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string name,
- double value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getDateField")]
- public static extern int GetDateField(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string name);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_setDateField")]
- public static extern int SetDateField(
- nint thread,
- InstrumentProfileHandle ip,
- [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string name,
- int value);
-
- [DllImport(
- ImportInfo.DllName,
- CallingConvention = CallingConvention.Cdecl,
- CharSet = CharSet.Ansi,
- ExactSpelling = true,
- BestFitMapping = false,
- ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfile_getNonEmptyCustomFieldNames")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ListMarshaler))]
- public static extern List GetNonEmptyCustomFieldNames(
- nint thread,
- InstrumentProfileHandle ip);
- }
-}
diff --git a/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileNative.cs b/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileNative.cs
new file mode 100644
index 00000000..b871e3e1
--- /dev/null
+++ b/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileNative.cs
@@ -0,0 +1,47 @@
+//
+// Copyright © 2025 Devexperts LLC. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+//
+
+using System;
+using System.Runtime.InteropServices;
+using DxFeed.Graal.Net.Native.Interop;
+
+namespace DxFeed.Graal.Net.Native.Ipf;
+
+[StructLayout(LayoutKind.Sequential)]
+internal record struct InstrumentProfileNative(
+ StringNative Type,
+ StringNative Symbol,
+ StringNative Description,
+ StringNative LocalSymbol,
+ StringNative LocalDescription,
+ StringNative Country,
+ StringNative OPOL,
+ StringNative ExchangeData,
+ StringNative Exchanges,
+ StringNative Currency,
+ StringNative BaseCurrency,
+ StringNative CFI,
+ StringNative ISIN,
+ StringNative SEDOL,
+ StringNative CUSIP,
+ int ICB,
+ int SIC,
+ double Multiplier,
+ StringNative Product,
+ StringNative Underlying,
+ double SPC,
+ StringNative AdditionalUnderlyings,
+ StringNative MMY,
+ int Expiration,
+ int LastTrade,
+ double Strike,
+ StringNative OptionType,
+ StringNative ExpirationStyle,
+ StringNative SettlementStyle,
+ StringNative PriceIncrements,
+ StringNative TradingHours,
+ IntPtr CustomFields,
+ int Hash);
diff --git a/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileReaderHandle.cs b/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileReaderHandle.cs
index 0cb33c65..8ae8a4e1 100644
--- a/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileReaderHandle.cs
+++ b/src/DxFeed.Graal.Net/Native/Ipf/InstrumentProfileReaderHandle.cs
@@ -1,5 +1,5 @@
//
-// Copyright © 2024 Devexperts LLC. All rights reserved.
+// Copyright © 2025 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
@@ -19,6 +19,8 @@ namespace DxFeed.Graal.Net.Native.Ipf;
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Global", Justification = "Created by marshaler")]
internal sealed class InstrumentProfileReaderHandle : JavaHandle
{
+ private static readonly InstrumentProfileMarshaler _marshaler = new();
+
public static string? ResolveSourceUrl(string address) =>
SafeCall(Import.ResolveSourceUrl(CurrentThread, address));
@@ -33,14 +35,14 @@ public bool WasComplete() =>
public unsafe List ReadFromFile(string address, string? user, string? password)
{
- var ptr = SafeCall(Import.ReadFromFile(CurrentThread, this, address, user, password));
+ SafeCall(Import.ReadFromFile(CurrentThread, this, address, user, password, out var ptr));
return ConvertToProfiles(ptr);
}
public unsafe List ReadFromFile(string address, AuthToken? authToken)
{
var tokenHandle = authToken == null ? new AuthTokenHandle() : authToken.Handle;
- var ptr = SafeCall(Import.ReadFromFile(CurrentThread, this, address, tokenHandle));
+ SafeCall(Import.ReadFromFile(CurrentThread, this, address, tokenHandle, out var ptr));
return ConvertToProfiles(ptr);
}
@@ -48,10 +50,11 @@ private unsafe List ConvertToProfiles(ListNative* han
{
try
{
- var profiles = new List();
+ var profiles = new List(handles->Size);
for (var i = 0; i < handles->Size; i++)
{
- profiles.Add(new InstrumentProfile(new InstrumentProfileHandle((IntPtr)handles->Elements[i])));
+ var profile = (InstrumentProfile)_marshaler.ConvertNativeToManaged((IntPtr)handles->Elements[i])!;
+ profiles.Add(profile);
}
return profiles;
@@ -110,8 +113,8 @@ public static extern int WasComplete(
ExactSpelling = true,
BestFitMapping = false,
ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfileReader_readFromFile2")]
- public static extern unsafe ListNative* ReadFromFile(
+ EntryPoint = "dxfg_InstrumentProfileReader_readFromFile8")]
+ public static extern unsafe int ReadFromFile(
nint thread,
InstrumentProfileReaderHandle reader,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
@@ -119,7 +122,8 @@ public static extern int WasComplete(
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
string? user,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string? password);
+ string? password,
+ out ListNative* profiles);
[DllImport(
ImportInfo.DllName,
@@ -128,13 +132,14 @@ public static extern int WasComplete(
ExactSpelling = true,
BestFitMapping = false,
ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_InstrumentProfileReader_readFromFile3")]
- public static extern unsafe ListNative* ReadFromFile(
+ EntryPoint = "dxfg_InstrumentProfileReader_readFromFile9")]
+ public static extern unsafe int ReadFromFile(
nint thread,
InstrumentProfileReaderHandle reader,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
string address,
- AuthTokenHandle authToken);
+ AuthTokenHandle authToken,
+ out ListNative* profiles);
[DllImport(
ImportInfo.DllName,
@@ -143,8 +148,8 @@ public static extern int WasComplete(
ExactSpelling = true,
BestFitMapping = false,
ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_CList_InstrumentProfile_wrapper_release")]
- public static extern unsafe ListNative* ReleaseListWrapper(
+ EntryPoint = "dxfg_instrument_profile2_list_free")]
+ public static extern unsafe int ReleaseListWrapper(
nint thread,
ListNative* list);
}
diff --git a/src/DxFeed.Graal.Net/Native/Ipf/IterableInstrumentProfileHandle.cs b/src/DxFeed.Graal.Net/Native/Ipf/IterableInstrumentProfileHandle.cs
index 35df6acd..dc4b47bc 100644
--- a/src/DxFeed.Graal.Net/Native/Ipf/IterableInstrumentProfileHandle.cs
+++ b/src/DxFeed.Graal.Net/Native/Ipf/IterableInstrumentProfileHandle.cs
@@ -1,5 +1,5 @@
//
-// Copyright © 2022 Devexperts LLC. All rights reserved.
+// Copyright © 2025 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
@@ -15,6 +15,8 @@ namespace DxFeed.Graal.Net.Native.Ipf;
internal sealed class IterableInstrumentProfileHandle : JavaHandle
{
+ private static readonly InstrumentProfileMarshaler _marshaler = new();
+
public IterableInstrumentProfileHandle()
{
}
@@ -40,8 +42,16 @@ public bool HasNext() =>
public InstrumentProfile? Next()
{
- var i = NativeNext(CurrentThread, this);
- return i != null ? new InstrumentProfile(i) : null;
+ var ptr = IntPtr.Zero;
+ try
+ {
+ ErrorCheck.SafeCall(NativeNext(CurrentThread, this, out ptr));
+ return (InstrumentProfile?)_marshaler.ConvertNativeToManaged(ptr);
+ }
+ finally
+ {
+ _marshaler.CleanUpFromNative(ptr);
+ }
}
[DllImport(
@@ -63,8 +73,9 @@ private static extern int NativeHasNext(
ExactSpelling = true,
BestFitMapping = false,
ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_Iterable_InstrumentProfile_next")]
- private static extern InstrumentProfileHandle? NativeNext(
+ EntryPoint = "dxfg_Iterable_InstrumentProfile_next2")]
+ private static extern int NativeNext(
nint thread,
- IterableInstrumentProfileHandle iterable);
+ IterableInstrumentProfileHandle handle,
+ out IntPtr profile);
}
diff --git a/src/DxFeed.Graal.Net/Native/Schedules/ScheduleHandle.cs b/src/DxFeed.Graal.Net/Native/Schedules/ScheduleHandle.cs
index 419f86b0..01911603 100644
--- a/src/DxFeed.Graal.Net/Native/Schedules/ScheduleHandle.cs
+++ b/src/DxFeed.Graal.Net/Native/Schedules/ScheduleHandle.cs
@@ -1,15 +1,15 @@
//
-// Copyright © 2024 Devexperts LLC. All rights reserved.
+// Copyright © 2025 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
+using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using DxFeed.Graal.Net.Ipf;
using DxFeed.Graal.Net.Native.Interop;
-using DxFeed.Graal.Net.Native.Ipf;
using static DxFeed.Graal.Net.Native.ErrorHandling.ErrorCheck;
namespace DxFeed.Graal.Net.Native.Schedules;
@@ -17,17 +17,28 @@ namespace DxFeed.Graal.Net.Native.Schedules;
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Global", Justification = "Created by marshaler")]
internal sealed class ScheduleHandle : JavaHandle
{
- public static ScheduleHandle GetInstance(InstrumentProfile profile) =>
- SafeCall(Import.GetInstance(CurrentThread, profile.GetHandle()));
+ private static readonly StringMarshaler _marshaler = new();
+
+ public static ScheduleHandle GetInstance(InstrumentProfile profile)
+ {
+ SafeCall(Import.GetInstance(CurrentThread, profile, out var scheduleHandle));
+ return scheduleHandle;
+ }
public static ScheduleHandle GetInstance(string scheduleDefinition) =>
SafeCall(Import.GetInstance(CurrentThread, scheduleDefinition));
- public static ScheduleHandle GetInstance(InstrumentProfile profile, string venue) =>
- SafeCall(Import.GetInstance(CurrentThread, profile.GetHandle(), venue));
+ public static ScheduleHandle GetInstance(InstrumentProfile profile, string venue)
+ {
+ SafeCall(Import.GetInstance(CurrentThread, profile, venue, out var scheduleHandle));
+ return scheduleHandle;
+ }
- public static List GetTradingVenues(InstrumentProfile profile) =>
- SafeCall(Import.GetTradingVenues(CurrentThread, profile.GetHandle()));
+ public static unsafe List GetTradingVenues(InstrumentProfile profile)
+ {
+ SafeCall(Import.GetTradingVenues(CurrentThread, profile, out var venues));
+ return ConvertToStringList(venues);
+ }
public static void DownloadDefaults(string downloadConfig) =>
SafeCall(Import.DownloadDefaults(CurrentThread, downloadConfig));
@@ -65,6 +76,25 @@ public string GetName() =>
public string GetTimeZone() =>
SafeCall(Import.GetTimeZone(CurrentThread, this));
+ private static unsafe List ConvertToStringList(ListNative* handles)
+ {
+ try
+ {
+ var venues = new List(handles->Size);
+ for (var i = 0; i < handles->Size; i++)
+ {
+ var profile = (string)_marshaler.ConvertNativeToManaged((IntPtr)handles->Elements[i])!;
+ venues.Add(profile);
+ }
+
+ return venues;
+ }
+ finally
+ {
+ SafeCall(Import.ReleaseList(CurrentThread, (IntPtr)handles));
+ }
+ }
+
private static class Import
{
[DllImport(
@@ -74,10 +104,12 @@ private static class Import
ExactSpelling = true,
BestFitMapping = false,
ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_Schedule_getInstance")]
- public static extern ScheduleHandle GetInstance(
+ EntryPoint = "dxfg_Schedule_getInstance4")]
+ public static extern int GetInstance(
nint thread,
- InstrumentProfileHandle profile);
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(InstrumentProfileMarshaler))]
+ InstrumentProfile profile,
+ out ScheduleHandle handle);
[DllImport(
ImportInfo.DllName,
@@ -99,12 +131,14 @@ public static extern ScheduleHandle GetInstance(
ExactSpelling = true,
BestFitMapping = false,
ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_Schedule_getInstance3")]
- public static extern ScheduleHandle GetInstance(
+ EntryPoint = "dxfg_Schedule_getInstance5")]
+ public static extern int GetInstance(
nint thread,
- InstrumentProfileHandle profile,
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(InstrumentProfileMarshaler))]
+ InstrumentProfile profile,
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
- string venue);
+ string venue,
+ out ScheduleHandle handle);
[DllImport(
ImportInfo.DllName,
@@ -113,11 +147,12 @@ public static extern ScheduleHandle GetInstance(
ExactSpelling = true,
BestFitMapping = false,
ThrowOnUnmappableChar = true,
- EntryPoint = "dxfg_Schedule_getTradingVenues")]
- [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ListMarshaler))]
- public static extern List GetTradingVenues(
+ EntryPoint = "dxfg_Schedule_getTradingVenues2")]
+ public static extern unsafe int GetTradingVenues(
nint thread,
- InstrumentProfileHandle profile);
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(InstrumentProfileMarshaler))]
+ InstrumentProfile profile,
+ out ListNative* handle);
[DllImport(
ImportInfo.DllName,
@@ -232,5 +267,12 @@ public static extern DayHandle GetDayByYearMonthDay(
EntryPoint = "dxfg_Schedule_getTimeZone")]
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StringMarshaler))]
public static extern string GetTimeZone(nint thread, ScheduleHandle schedule);
+
+ [DllImport(
+ ImportInfo.DllName,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Ansi,
+ EntryPoint = "dxfg_CList_String_release")]
+ public static extern int ReleaseList(nint thread, nint handle);
}
}
diff --git a/tests/DxFeed.Graal.Net.Tests/Api/DXEndpointTest.cs b/tests/DxFeed.Graal.Net.Tests/Api/DXEndpointTest.cs
index eae32a76..dcae93da 100644
--- a/tests/DxFeed.Graal.Net.Tests/Api/DXEndpointTest.cs
+++ b/tests/DxFeed.Graal.Net.Tests/Api/DXEndpointTest.cs
@@ -1,10 +1,9 @@
//
-// Copyright © 2022 Devexperts LLC. All rights reserved.
+// Copyright © 2025 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
-using System.Net.NetworkInformation;
using DxFeed.Graal.Net.Api;
using DxFeed.Graal.Net.Api.Osub;
using DxFeed.Graal.Net.Events;
@@ -18,12 +17,15 @@ namespace DxFeed.Graal.Net.Tests.Api;
[TestFixture]
public class DXEndpointTest
{
+ private static readonly Random rnd = new();
+
[Test]
public void ConnectToLocalPublisher()
{
+ var port = rnd.Next(48658, 49150);
var countdownEvent = new CountdownEvent(1);
- var pub = Create(Publisher).Connect(":5679");
+ var pub = Create(Publisher).Connect($":{port}");
var feed = Create(Feed);
feed.AddStateChangeListener((_, newState) =>
{
@@ -32,7 +34,7 @@ public void ConnectToLocalPublisher()
countdownEvent.Signal();
}
});
- feed.Connect("localhost:5679");
+ feed.Connect($"localhost:{port}");
Assert.That(countdownEvent.Wait(new TimeSpan(0, 0, 3)), Is.True);
pub.Close();
feed.Close();
diff --git a/tests/DxFeed.Graal.Net.Tests/Ipf/InstrumentProfileTests.cs b/tests/DxFeed.Graal.Net.Tests/Ipf/InstrumentProfileTests.cs
index d30fb7d5..28b9d6c5 100644
--- a/tests/DxFeed.Graal.Net.Tests/Ipf/InstrumentProfileTests.cs
+++ b/tests/DxFeed.Graal.Net.Tests/Ipf/InstrumentProfileTests.cs
@@ -1,5 +1,5 @@
//
-// Copyright © 2024 Devexperts LLC. All rights reserved.
+// Copyright © 2025 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
@@ -74,6 +74,7 @@ public void AddNonEmptyCustomFieldNames_ShouldReturnTrueForNonEmptyField()
{
Assert.That(profile.AddNonEmptyCustomFieldNames(expectedFieldNames), Is.True);
Assert.That(actualFieldNames.SetEquals(expectedFieldNames), Is.True);
+ Assert.That(profile.AddNonEmptyCustomFieldNames(expectedFieldNames), Is.False);
});
}
@@ -87,6 +88,13 @@ public void CopyConstructor_ShouldShouldCopyAllFields()
Assert.That(profile.GetHashCode(), Is.EqualTo(CreateTestProfile().GetHashCode()));
Assert.That(profile, Is.EqualTo(CreateTestProfile()));
});
+ var profile1 = new InstrumentProfile(profile);
+ profile.SetField("Field1", "NewValue");
+ Assert.Multiple(() =>
+ {
+ Assert.That(profile.GetField("Field1"), Is.EqualTo("NewValue"));
+ Assert.That(profile1.GetField("Field1"), Is.EqualTo("Test"));
+ });
}
[Test]
diff --git a/tests/DxFeed.Graal.Net.Tests/Schedules/ScheduleTest.cs b/tests/DxFeed.Graal.Net.Tests/Schedules/ScheduleTest.cs
index 4c730afe..997226df 100644
--- a/tests/DxFeed.Graal.Net.Tests/Schedules/ScheduleTest.cs
+++ b/tests/DxFeed.Graal.Net.Tests/Schedules/ScheduleTest.cs
@@ -1,5 +1,5 @@
//
-// Copyright © 2024 Devexperts LLC. All rights reserved.
+// Copyright © 2025 Devexperts LLC. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
@@ -40,7 +40,7 @@ public void Day_ShouldReturnsNullValueForInvalidDay()
{
var profiles = new InstrumentProfileReader().ReadFromFile(TestIpf);
foreach (var profile in profiles) {
- var schedule = Schedule.GetInstance(profile);
+ var schedule = Schedule.GetInstance(profile.TradingHours);
var day = schedule.GetDayByYearMonthDay(01011950);
Assert.Multiple(() =>
{
@@ -53,4 +53,14 @@ public void Day_ShouldReturnsNullValueForInvalidDay()
});
}
}
+
+ [Test]
+ public void Schedule_ShouldReturnCorrectVenues()
+ {
+ var profiles = new InstrumentProfileReader().ReadFromFile(TestIpf);
+ var aapl = profiles.Find(profile => profile.Symbol.Equals("AAPL", StringComparison.Ordinal));
+ var venues = Schedule.GetTradingVenues(aapl ?? throw new InvalidOperationException());
+ Assert.That(venues, Has.Count.EqualTo(1));
+ Assert.That(venues[0], Is.EqualTo("NewYorkETH"));
+ }
}