powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Маршалинг возвращаемого значения
25 сообщений из 26, страница 1 из 2
Маршалинг возвращаемого значения
    #32764096
Adfg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет!
Помогите, пожалуйста определить функцию:
Код: plaintext
RateInfo*    MtGetRates(const int handle,char *symbol,int period,time_t lasttime,int *counter);


В counter возвращается число элементов в возвращаемом массиве (RateInfo*).
Я попробовал переписать вот так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
    public struct TRateInfo
    {    public int    Field1;
        public double   Field2;
        public int      Field3;
    };

    [DllImport("moneylib.dll")]
    [return:MarshalAs(UnmanagedType.LPArray, SizeParamIndex=4)]
    public static extern TRateInfo[] MtGetRates(int Handle, string Symbol, TPeriod Period, int LastTime, out int ArrayLength);
но это не работает - во время выполнения:"MarshalDirectiveException - "Can not marshal return value"".
Как нужно написать?
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32764141
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
как вариант: возвращай IntPtr и в цикле заполни массив структур TRateInfo через Marshal.PtrToStructure
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32765511
Adfg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Списибо, но не приведете ли простой примерчик на "заполние массива через Marshal.PtrToStructure". Плииииз!
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32765534
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
например:
Код: plaintext
1.
[DllImport("moneylib.dll")]
public static extern IntPtr MtGetRates(int Handle, string Symbol, int Period, int LastTime, out int ArrayLength);

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
IntPtr ptr, org;
int    count;
				
org=ptr=MtGetRates(35353, "am-cs", 78, 87, out count);

TRateInfo[] ri=new TRateInfo[count];
				
for(int i=0; i<count; i++, ptr=new IntPtr(ptr.ToInt32()+Marshal.SizeOf(typeof(TRateInfo))))
{
  ri[i]=(TRateInfo)Marshal.PtrToStructure(ptr, typeof(TRateInfo));		
}
// освободить память -> org
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32765556
taj
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ээ... не знаю, работает ли это, но попробуй, пока кузя не пришел ;)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
ArrayList rates = new ArrayList();
int i= 0 ;
int size = Marshal.SizeOf(Type.GetType("TRateInfo"));

IntPtr rateptr = MtGetRates(...);

for (i= 0 ; i<counter; i++)
{
	rateptr = new IntPtr((int)rateptr + i*size);
	
	rates.Add( (TRateInfo)Marshal.PtrToStructure(rateptr, typeof(TRateInfo)) );
}
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32765575
taj
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
о, во-первых кузя пришел (привет, кузя), во-вторых у меня ошибка в коде, не (int)rateptr + i*size, а ((int)rateptr + size, и поместить ее надо ниже строки с rates.Add(), ну в общем-то уже неважно ;)
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32765582
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 taj
привет :)

предупреждать надо,
что ж это мы с тобой на пару практически один и тот же код пишем ?
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32765618
Adfg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
СПАСИБО ОГРОМНОЕ ОБОИМ!!! :))
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32765704
Adfg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
И еще пара маленьких вопросиков вдогонку, если вы не против. :)
1. Как проверить IntPtr на равеноство c null? (функция при ошибках возвращает "null")
2. Кузя:"// освободить память -> org". А как это, собственно, сделать? ;)
И где можно про это почитать в MSDN: когда надо освобождать а когда не надо.... вообще-то на http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconmemorymanagement.asp написано следующее:
"The interop marshaler always attempts to free memory allocated by unmanaged code. This behavior complies with COM memory management rules, but differs from the rules that govern native C++.

Confusion can arise if you anticipate native C++ behavior (no memory freeing) when using platform invoke, which automatically frees memory for pointers.".
Что бы это значило???
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32765739
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. проверка на нулевое значение
Код: plaintext
1.
2.
if(ptr==IntPtr.Zero)
{ ...
}

2. надо смотреть документацию на твою функцию MtGetRates. в ней (документации) д.б. примерно такие слова

This buffer is allocated by the system and must be freed using the NetApiBufferFree function.
или
To free a block of memory, use the HeapFree function.
или
The calling application is responsible for freeing the returned PIDL by using the Shell allocator's IMalloc::Free method.
и т.д.

и вызвать соответствующую функцию освобождения памяти (опять же через PInvoke или Marshal.FreeCoTaskMem, Marshal.FreeHGlobal) и передать ей указатель на на эту память (см. IntPtr org;)
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32765777
Adfg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
1.
//if(ptr==IntPtr.Zero)
Спасибо.
2. В описании есть слова:
"Массив должен быть освобождён при помощи функции HeapFree( GetProcessHeap(), 0, pRates );" т.е. мне Invoke'ить HeapFree?
3. Относительно Marshal.FreeCoTaskMem, Marshal.FreeHGlobal...
Я думал это только при освобождении блоков памяти, полученных при вызове соответственно Marshal.AllocCoTaskMem, Marshal.AllocHGlobal; разве это не так?
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32765788
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2. и HeapFree() и GetProcessHeap()

3. or any equivalent unmanaged API method
FreeHGlobal освобождает память, полученную, например, по GlobalAlloc() внутри unmanaged функции

---
PS: чтоб долго не искать

Код: plaintext
1.
2.
3.
  [DllImport("kernel32.dll")]
  static extern IntPtr GetProcessHeap();   
  [DllImport("kernel32.dll")]
  static extern bool HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem);

PPS.
есть интересный и полезный ресурс PINVOKE.NET
там собраны практически все сигнатуры для PInvoke
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32769431
Adfg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо!
Но у меня опять возникли сложности при маршалинге... помогите, плиз.
Есть перечисление:
Код: plaintext
1.
2.
3.
4.
5.
	public enum TOp
	{	Op1,
		Op2,
		Op3,
		Op4,
	};
и такая структура:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
	[StructLayout(LayoutKind.Sequential)]
	public struct TRecord
	{
		public int	Order;
		public int	Login;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst=8)]
		public string	Symbol;
		public short	Digits;
		public TOp	Command;
		public int		Volume;
	}
Как и раньше, есть функция, возвращающая массив структур TRecord. Я его обрабатываю, как и в предыдущем случае (с помющью IntPtr и т.п.). Но! У Unmanaged-версии структуры TRecord член Command имеет тип short . Поэтому при работе кода, приведенного выше, вторая половина возвращаемых структур TRecord получается испорченной.
Если написать:
Код: plaintext
1.
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst=8)]
		public TOp	Command; 
то во время выполнения возникает исключение "Type TRecord can not be marshaled as unmanaged structure; no meaningfull size or offset can be comoputed." (это потому что внутри managed-прототипа функции есть строки Marshal.SizeOf(typeof(TRecord));)
Что надо написать?
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32769441
Adfg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ошибочка получилась - третий кусок кода в предыдущем посте такой:
Код: plaintext
1.
		[MarshalAs(UnmanagedType.U2)]
		public TOp	Command;
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32769712
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
попробуй указать:
Код: plaintext
1.
2.
3.
public enum TOp : short
{	Op1,
	...
};
иначе несогласование типов, понимаешь ...
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32771753
Adfg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Это не помогло.... но я вручную преобразовал все значения short в TOp, так что все нормально... было.... пока не начал переписывать под .Net следующий кусок кода:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
#pragma pack(8)

struct ConSession
  {
   short         open_hour,open_min;
   short         close_hour,close_min;
   short         open_hour2,open_min2;
   short         close_hour2,close_min2;
   short         open_hour3,open_min3;
   short         close_hour3,close_min3;
   int           open,close;           
   int           open2,close2;         
   int           open3,close3;         
  };
struct ConSecurity
  {
   char         name[8];           
   char         description[64];   
   char         source[8];         
   char         secname[16];       
   int          type;              
   int          logging;           
   int          indirect;          
   int          filter;            
   double       point;             
   double       multiply;          
   int          stops;             
   double       tickvalue;         
   double       tickvalue2;        
   double       ticksize;          
   time_t       starting;          
   time_t       expiration;        
   ConSession   days[7];           
   int          unused[16];        
   ConSecurity   *next;                // ссылка на следующий объект
  };

ConSecurity* MtGetSecurities(const int handle,int *items); // в items - количество элементов в возвращаемом массиве
У меня получилось следующее:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
	[StructLayout(LayoutKind.Sequential, Pack=8, CharSet=CharSet.Ansi)]
	public struct TConSession
	{	public short	Open_Hour;
		public short	Open_Min;
		public short	Сlose_Hour;
		public short	Close_Min;
		public short	Open_Hour2;
		public short	Open_Min2;
		public short	Close_Hour2;
		public short	Close_Min2;
		public short	Open_Hour3;
		public short	Open_Min3;
		public short	Close_Hour3;
		public short	Close_Min3;
		public int		Open;
		public int		Close;           // расчитанные значения в минутах
		public int		Open2;
		public int		Close2;         // расчитанные значения в минутах
		public int		Open3;
		public int		Close3;         // расчитанные значения в минутах
	};

	[StructLayout(LayoutKind.Sequential, Pack=8, CharSet=CharSet.Ansi)]
	public struct TConSecurity
  {
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst=8)]
		public string	Name;         
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst=64)]
		public string	Description;  
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst=8)]
		public string	Source;       
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst=16)]
		public string	SecName;      
		public int	Type;                 
		public int	Logging;              
		public int	Indirect;             
		public int	Filter;               
		public double	Point;                
		public double	Multiply;             
		public int	Stops;                
		public double	TickValue;            
		public double	TickValue2;           
		public double	TickSize;             
		public int	Starting;             
		public int	Expiration;           
		[MarshalAs(UnmanagedType.ByValArray, SizeConst=7)]
		public TConSession[]	Days;   
		[MarshalAs(UnmanagedType.ByValArray, SizeConst=16)]
		public int[]	Unused;            
		public IntPtr	Next;      
	};


		[DllImport("mtapi.dll")]
		public static extern IntPtr MtGetSecurities(int Handle, out int ArrayLength);

		public static TConSecurity[] GetSecurities(int Handle)
		{	int ArrLength = 0;
			IntPtr ptr, org;
			int StructSize = Marshal.SizeOf(typeof(TConSecurity));

			org=ptr=MtGetSecurities(Handle, out ArrLength);

			TConSecurity[] tr = new TConSecurity[ArrLength];

			if (ptr != IntPtr.Zero)
			{	for(int i=0; i<ArrLength; i++, ptr=new IntPtr(ptr.ToInt32()+StructSize))
				{	tr[i]=(TConSecurity)Marshal.PtrToStructure(ptr, typeof(TConSecurity));
				};

				HeapFree(GetProcessHeap(), 0, org);
			};

			return tr;
		}
Но это не работает!!! Причем ему не нравится аттрибут у поля public TConSession[] Days; - во время выполнения возникает исключение "Type TRecord can not be marshaled as unmanaged structure; no meaningfull size or offset can be comoputed." Если [MarshalAs(UnmanagedType.ByValArray, SizeConst=7)] убрать, то все работает без исключений, но, естественно, все данные в возвращаемом массиве TConSecurity[] начиная со второго элемента (точнее, с середины первого) оказыватся испорченными.
ПОМОГИТЕ ПЛИЗ!
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32771807
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
маршалинг структуры, включающей в себя массив другой структуры "по значению", не поддерживается
(только массивы из известных типов).
--
варианты (в порядке возрастания геморроя):
замени массив структур на 7 последовательных элементарных структур

используй MC++ для interop'a

используй классы вместо структур
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32771814
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
+
замени массив структур на эквивалентный по длине массив байт. после возврата можно сделать преобразование по Buffer.BlockCopy(..);
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32771818
Adfg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>>маршалинг структуры, включающей в себя массив другой структуры "по значению", не поддерживается
Я так и думал.... т.к. когда оставляешь только "[MarshalAs(UnmanagedType.ByValArray, SizeConst=16)] public int[] Unused; ", то все проходит нормально.
>>используй MC++ для interop'a
Что такое MC++?
>>используй классы вместо структур
Да я пробовал, но там, по-моему, никакой принципиальной разницы... все равно все упирается в этот чертов "public TConSession[] Days;". Или, наверное, я не правильно понимаю... а как так (через классы) можно сделать?
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32771825
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AdfgЧто такое MC++?Managed Extensions for C++. делаешь отдельную сборку, в которой и общаешься со своей библиотекой "в лоб". Adfg... а как так (через классы) можно сделать?тогда воздержись :) - очень длинная история...
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32771849
Adfg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
>>Managed Extensions for C++.
понял.
>>тогда воздержись :) - очень длинная история...
да ладно тебе! расскажи, плиз, коротенько-то... :)
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32771855
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если уж совсем коротко :)
посмотри статейку C Sharp Ripper
там в самом конце есть раздельчик Some translation details
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32771864
Adfg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну вобщем понятно, только там написано, что самое интересное - содержание метода
Код: plaintext
1.
2.
3.
4.
5.
  public TRACK_DATA this [int Index]
  {
    get
    { /* Code in the source files */
    }
  }
находится в исходниках, а исходники (по ссылке вверху страницы) они скачивать почему-то не дают...
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32771869
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Adfg... а исходники (по ссылке вверху страницы) они скачивать почему-то не дают...
зарегистрироваться надо :)
лови (40.2 kb)
...
Рейтинг: 0 / 0
Маршалинг возвращаемого значения
    #32771871
кузя
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PS
кстати, у них можно и зарегистрироваться и получать подписку на интересные статьи по .net (~1 раз в 3-4 недели). среди них попадаются очень даже ничего (в смысле идеи и/или реализации), могут когда нибудь и пригодиться.
...
Рейтинг: 0 / 0
25 сообщений из 26, страница 1 из 2
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Маршалинг возвращаемого значения
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]