Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Маршалинг возвращаемого значения / 25 сообщений из 26, страница 1 из 2
01.11.2004, 22:52
    #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
02.11.2004, 01:28
    #32764141
кузя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Маршалинг возвращаемого значения
как вариант: возвращай IntPtr и в цикле заполни массив структур TRateInfo через Marshal.PtrToStructure
...
Рейтинг: 0 / 0
02.11.2004, 18:24
    #32765511
Adfg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Маршалинг возвращаемого значения
Списибо, но не приведете ли простой примерчик на "заполние массива через Marshal.PtrToStructure". Плииииз!
...
Рейтинг: 0 / 0
02.11.2004, 18:40
    #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
02.11.2004, 18:54
    #32765556
taj
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
02.11.2004, 19:08
    #32765575
taj
taj
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Маршалинг возвращаемого значения
о, во-первых кузя пришел (привет, кузя), во-вторых у меня ошибка в коде, не (int)rateptr + i*size, а ((int)rateptr + size, и поместить ее надо ниже строки с rates.Add(), ну в общем-то уже неважно ;)
...
Рейтинг: 0 / 0
02.11.2004, 19:16
    #32765582
кузя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Маршалинг возвращаемого значения
2 taj
привет :)

предупреждать надо,
что ж это мы с тобой на пару практически один и тот же код пишем ?
...
Рейтинг: 0 / 0
02.11.2004, 19:58
    #32765618
Adfg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Маршалинг возвращаемого значения
СПАСИБО ОГРОМНОЕ ОБОИМ!!! :))
...
Рейтинг: 0 / 0
02.11.2004, 21:41
    #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
02.11.2004, 22:41
    #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
03.11.2004, 00:18
    #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
03.11.2004, 00:59
    #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
04.11.2004, 18:10
    #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
04.11.2004, 18:14
    #32769441
Adfg
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Маршалинг возвращаемого значения
Ошибочка получилась - третий кусок кода в предыдущем посте такой:
Код: plaintext
1.
		[MarshalAs(UnmanagedType.U2)]
		public TOp	Command;
...
Рейтинг: 0 / 0
04.11.2004, 23:45
    #32769712
кузя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Маршалинг возвращаемого значения
попробуй указать:
Код: plaintext
1.
2.
3.
public enum TOp : short
{	Op1,
	...
};
иначе несогласование типов, понимаешь ...
...
Рейтинг: 0 / 0
06.11.2004, 16:59
    #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
06.11.2004, 20:08
    #32771807
кузя
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Маршалинг возвращаемого значения
маршалинг структуры, включающей в себя массив другой структуры "по значению", не поддерживается
(только массивы из известных типов).
--
варианты (в порядке возрастания геморроя):
замени массив структур на 7 последовательных элементарных структур

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

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


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