jak zastąpić pole w strukturze void*

0

Witam wszystkich,
próbuje zrobić wrappera z c++ do c# i w końcu natrafiłem na problem, otóż chce odbierać obraz video po ramkach i do tych ramek stworzona jest struktura

struct frame
{void * 	buf
sizet	size
timestampt	timestamp
int	bit_info}  

gdzie buf to wskaźnik do bufora, size i timestap to inne struktury które już przekonwertowałem ale z tym void* nie wiem jak sobie poradzić w c#, muszę używać unsafe?
próbowałem coś takiego,

[StructLayout(LayoutKind.Sequential)]
struct frame
{
IntPtr buf
sizet size
timestampt timestammo
int bit_info
} 
0

IntPtr to dobry wybór.

0

ok, zadziałało, jak teraz mogę użyć informacji zawartej buf'ie?

0

ok dziękuję Rev, na razie nie mam pytań :)

0

Witam, już mam pytanie dotyczącą odebrania kolejnej struktury, otóż mam w c++ coś takiego:

 struct foo
{
	int id;
	char[12] name;
	struct
    	{
		unsigned index;
		type_t type;
		int dir;
		status status;
		union {
	    		struct {
				int conf_slot;
	    		} aud;
			struct {
				int win_in;
				int cap_dev;
	    		} vid;
		} stream;
    	} media[MAX_SDP];
}
</code=cpp>
type_t, i status to kolejne stuktury ale z nimi sobie poradziłem i wiem że na pewno działa, z kolei mam problem z media[max_sdp]  czy dobrze zmarshalowałem i nie jestem pewien co do tego union, albo może problem tkwi w czymś innym, robie coś takiego:
```csharp
[StructLayout(LayoutKind.Sequential)]
    public struct foo
    {
        int id;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
	string name;
	
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public mediat_[] media;

        [StructLayout(LayoutKind.Sequential)]
        public struct mediat_
        {
            public uint index;
            public typet type;
            public int dir;
            statust status;
            public streamt_ stream;
        }
        [StructLayout(LayoutKind.Explicit)]
        public struct streamt_
        {
            [FieldOffset(0)]
            public audt_ aud;
            [FieldOffset(4)]
            public vidt_ vid;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct audt_
        {
            public int conf_slot;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct vidt_
        {
            public int win_in;
            public int cap_dev;
        }  
    } 

i to powoduje że pojawia mi się taki komunikat:

System.TypeLoadException was unhandled
Message="Nie można załadować typu 'foo' z zestawu 'dllwrapper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'."
Source="Test2"
TypeName="dllwrapper.foo"

z kolei jeśli robię coś takiego:

...
        public mediat_ media;
	...
        [StructLayout(LayoutKind.Sequential, Size = 384)]
        public struct mediat_{
		...
	}...
        } 

To wtedy się nie wykłada program, odczytuje wartości z tej struktury dla miedia[0] niestety interesują mnie informacje zawarte w miedia[1] ale nie mogę się tam dostać, kiedy próbowałem dodać

 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public mediat_[] media;

do tej struktury także pojawiał się bład, co prawda inny niż ten wyżej ale mówiący o nieprawidłowej strukturze. Dziwi mnie też to że udało mi się odebrać strukturę która miała także stukture w strukturze typu [] i tam "poszło" od razu, więc myślę że może z tym union coś jest nie tak...
i jeszcze jedno pytanie da się zastąpić #define z c++ jakoś? i kolejne dotyczący importowania enuma jak ugryźć coś takiego?

enum  format_id { 
   FORMAT_L16 = 0, 
   FORMAT_PCM = FORMAT_L16, 
   FORMAT_PCMA = FORMAT_PACK('A', 'L', 'A', 'W'),
   FORMAT_ALAW = FORMAT_PCMA,...
}; 

gdzie

#define FORMAT_PACK(C1, C2, C3, C4) FOURCC(C1, C2, C3, C4)
#define FOURCC(C1, C2, C3, C4) ( C4<<24 | C3<<16 | C2<<8 | C1 )

uff to chyba wszystko z moich niewiadomych.

0

jeden problem rozwiązałem, należało

public struct foo
    {
        int id;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
        string name;
 
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public mediat_[] media;
 
        
    }[StructLayout(LayoutKind.Sequential)]
        public struct mediat_
        {
            public uint index;
            public typet type;
            public int dir;
            statust status;
            public streamt_ stream;
        }
        [StructLayout(LayoutKind.Explicit)]
        public struct streamt_
        {
            [FieldOffset(0)]
            public audt_ aud;
            [FieldOffset(4)]
            public vidt_ vid;
        }
 
        [StructLayout(LayoutKind.Sequential)]
        public struct audt_
        {
            public int conf_slot;
        }
        [StructLayout(LayoutKind.Sequential)]
        public struct vidt_
        {
            public int win_in;
            public int cap_dev;
        }    

należało wywalić wewnętrzne struktury na zewnątrz i wszystko działa, pozostaje tylko enum z #define,
define zamieniłem na funkcje i generalnie chyba dobrze zamienia jednak wciąż nie wiem jak zrobić enuma z funkcją w środku...

0

nie wiem jak zrobić enuma z funkcją w środku...

nie robić.

FORMAT_PCMA = 'A' <<24 | 'L' <<16 | 'A' <<8 | 'W'

czy jakoś tak. brać pod uwagę, że char w C# jest dwubajtowy, więc dla zachowania tej samej wartości co w C być może trzeba nałożyć maskę 8-bitową:

  FORMAT_PCMA = (byte)'A' <<24 | (byte)'L' <<16 | (byte)'A' <<8 | (byte)'W'

albo

  FORMAT_PCMA = ('A'&0xFF) <<24 | ('L'&0xFF) <<16 | ('A'&0xFF) <<8 | ('W'&0xFF)
0

ekstra ;) dziękuję za wszystkie podpowiedzi i rozwiązania, teraz już nic nie stanie mi na drodze (mam nadzieje ;P)

i tyle po mojej radości :) zastosowałem się do rozwiązania

PJMEDIA_FORMAT_PCMA = (byte)'A' << 24 | (byte)'L' << 16 | (byte)'A' << 8 | (byte)'W'

ale także spróbowałem bez (byte) a także zamiast (byte)

FORMAT_PCMA = ('A'&0xFF) <<24 | ('L'&0xFF) <<16 | ('A'&0xFF) <<8 | ('W'&0xFF)

niestety pojawił się błąd o treści:

System.TypeLoadException was unhandled
Message="Nie można załadować typu 'info_t' z zestawu 'dllwrapper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null', ponieważ zawiera on pole obiektu o przesunięciu 8', ktre jest nieprawidłowo wyrwnane lub częściowo pokrywa się z polem niebędącym polem obiektu."
(PS cytat z VS2008, "ktre", "wywnanane")]
Generalnie mogłem coś nabroić z innymi typami ale nigdzie poza enumem format nie miałem przesunięcia, jakiś pomysł na obejście tego?

przepraszam, moja wina, tam jest wszystko ok, pomyliłem się i dałem za mały offset w pewnej strukturze która była częścią pewnej unii...
przepraszam zastanowię się dwa razy, zanim znowu zacznę pisać głupoty... za długo już nad tym siedzę
PS. enum działa także bez (byte)

0

Witam, ciąg dalszy problemów ze strukturami, tym razem natrafiłem na coś takiego

 struct foo
{
	bar* buf;
}
struct bar
{
	int bac;
	int kup;

}

ok, w c# zrobiłem jedna i drugą tak:

[StructLayout(LayoutKind.Sequential)]
struct foo
{
	//Marshal.PtrToStructure(buf, bar);
	IntPtr buf;
}
[StructLayout(LayoutKind.Sequential)]
struct bar
{
	int bac;
	int kup

}

i to działa, tylko jak teraz dostać się do danych z bar'a? jest coś takiego Marshal.PtrToStructure (jeszcze nie testowałem, ale to raczej to) tylko jak teraz zrobić coś takiego abym miał miał odzwierciedlenie 1:1 w strukturze (w sensie żebym mógł sobie napisać foo.bar.bac a jednocześnie mógł odbierać informacje bezpośrednio z funkcji c++)?

i jeszcze jedno pytanie bo pewnie i tak je zadam, jeszcze nie doszedłem do momentu ale widziałem w strukturze wskaźnik na inną strukturę która miała sobie wskaźniki do funkcji, jakiś pomysł?

0

Witam (w końcu się zarejestrowałem), natrafiłem na dość dziwny błąd, otóż:
posiadam pewną strukturę (format) która ma w sobie unie, i ową strukturę używam w dwóch innych strukturach (video_device_info oraz video_codec_param) w ta pierwsza wygląda następująco:

 [StructLayout(LayoutKind.Sequential)]
    public video_device_info
    {
        public int id;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public string name;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public **format[]** fmt;

i ta struktura działa, natomiast w ta druga wygląda tak:

[StructLayout(LayoutKind.Sequential)]
    public struct video_codec_param
    {
        public dirt dir;
        public video_packing packing;
        public **format** enc_fmt;
        public codec_fmtp enc_fmtp;      
        public int enc_mtu;
        public **format** dec_fmt;
        public codec_fmtp dec_fmtp;
        public int ignore_fmtp;
    } 

struktura format wygląda tak:

 [StructLayout(LayoutKind.Sequential)]
    public struct format
    {
        public uint id;
        public typet type;
        public format_detail detail_type;
        public det_t det;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct det_t
    {
        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.Struct)]
        public audio_t aud;
        [FieldOffset(36)]
        [MarshalAs(UnmanagedType.Struct)]
        public video_t vid;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        [FieldOffset(60)]
        public char[] user;
    }

wszystkie typy nie wymienione są albo enum'ami albo innymi strukturami które działają (odbierałem każdą po kolei i jest ok).

przechodząc do sedna
wywołując funkcję która odbiera video_device_info działa bez zarzutu,ale jeśli chce odebrać video_codec_param (obie funkcje wywołuję w identyczny sposób

 int getInfo(int id, out video_device_info vdi);

oraz int getCodecParam(int id, out video_codec_param vcp)

 ) pojawia mi się błąd
> System.Runtime.InteropServices.MarshalDirectiveException was unhandled
>   Message="Podpis typu metody nie jest zgodny z elementem PInvoke."
 napisałem sobie do testowania osobną funkcje ` typ test(){... return typ;}` którą to odbieram poszczególne elementy (na razie oprócz det_t[tej najważniejszej]) ze struktury video_codec_param i podczas odbierania struktury format dostaje ten sam błąd. Nie rozumiem czemu z video_device_info nie wyskakuję żaden błąd a video_codec_param już tak.
0

wątpię, żeby ktoś ogarniał co się dzieje w twoim kodzie po małych fragmentach. najlepiej jakbyś dał całość jakoś.

0

Witam, w weekend udało mi się zrobić, aby nie wyrzucał błędu, i także udało mi się coś odebrać, należało zrobić coś takiego

[StructLayout(LayoutKind.Explicit, Size=24)]
    public struct det_t
    {
        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.Struct)]
        public audio_t aud;
        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.Struct)]
        public video_t vid;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        [FieldOffset(24)]
        public char[] user;
    }

jednak dane które odbieram są nie w kolejności, generalnie baardzo wymieszane, tam gdzie pierwotnie znajduję się 1001 u mnie w tym samym polu 3267044, oto

<plain>www.pjsip.org/docs/latest-2/pjmedia/docs/html/structpjmedia__vid__codec__param.htm

źródło struktury którą chcę odebrać, z c# natomiast mam takie coś:
```csharp
[StructLayout(LayoutKind.Sequential)]
    public struct pjmedia_vid_codec_param
    {
        public pjmedia_dir dir;
        public pjmedia_vid_packing packing;
        public pjmedia_format enc_fmt;
        public pjmedia_codec_fmtp enc_fmtp;      
        public uint enc_mtu;
        public pjmedia_format dec_fmt;
        public pjmedia_codec_fmtp dec_fmtp;
        public int ignore_fmtp;

    } 
public enum pjmedia_dir
    {
        PJMEDIA_DIR_NONE = 0,
        PJMEDIA_DIR_ENCODING = 1,
        PJMEDIA_DIR_CAPTURE = PJMEDIA_DIR_ENCODING,
        PJMEDIA_DIR_DECODING = 2,
        PJMEDIA_DIR_PLAYBACK = PJMEDIA_DIR_DECODING,
        PJMEDIA_DIR_RENDER = PJMEDIA_DIR_DECODING,
        PJMEDIA_DIR_ENCODING_DECODING = 3,
        PJMEDIA_DIR_CAPTURE_PLAYBACK = PJMEDIA_DIR_ENCODING_DECODING,
        PJMEDIA_DIR_CAPTURE_RENDER = PJMEDIA_DIR_ENCODING_DECODING
    }
public enum pjmedia_vid_packing
    {
        PJMEDIA_VID_PACKING_UNKNOWN,
        PJMEDIA_VID_PACKING_PACKETS = 1,
        PJMEDIA_VID_PACKING_WHOLE = 2
    }
[StructLayout(LayoutKind.Sequential)]
    public struct pjmedia_format
    {
        public uint id;
        public pjmedia_type type;
        public pjmedia_format_detail_type detail_type;
        public det_t det;
    }

    [StructLayout(LayoutKind.Explicit, Size=24)]
    public struct det_t
    {
        [FieldOffset(0)]
        public pjmedia_audio_format_detail aud;
        [FieldOffset(0)]
        public pjmedia_video_format_detail vid;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
        [FieldOffset(24)]
        public char[] user;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct pjmedia_audio_format_detail
    {
        public uint clock_rate;
        public uint channel_count;
        public uint frame_time_usec;
        public uint bits_per_sample;
        public int avg_bps;	
        public int max_bps;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct pjmedia_video_format_detail
    {
        public pjmedia_rect_size size;
        public pjmedia_ratio fps;
        public int avg_bps;
        public int max_bps;
    }
[StructLayout(LayoutKind.Sequential)]
    public struct pjmedia_rect_size
    {
        public uint w;
        public uint h;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct pjmedia_ratio
    {
        public int num;
        public int denum;
    }
[StructLayout(LayoutKind.Sequential)]
    public struct pjmedia_codec_fmtp
    {

        public uint cnt;
        [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 16)]
        public paramt_[] param;

        [StructLayout(LayoutKind.Sequential)]
        public struct paramt_
        {
            public pj_str_t name;
            public pj_str_t val;
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct pj_str_t
    {
        [MarshalAs(UnmanagedType.LPStr)]
        public string ptr;
        public int slen;
    }

funkcja którą próbuje odebrać dane wygląda następująco
w c++

/**
 * Get video codec parameters.
 *
 * @param codec_id	Codec ID.
 * @param param		Structure to receive video codec parameters.
 *
 * @return		PJ_SUCCESS on success, or the appropriate error code.
 */
PJ_DECL(pj_status_t) pjsua_vid_codec_get_param(const pj_str_t *codec_id,pjmedia_vid_codec_param *param);

u mnie w c# wygląda tak:

[DllImport(PJSIP_DLL,CallingConvention=CallingConvention.Cdecl)]
        public static extern int pjsua_vid_codec_get_param(ref pj_str_t codec_id, out pjmedia_vid_codec_param param);

czy jest taka możliwość aby deklaracje w różnych plikach miało znaczenie? np. pjmedia_format mam w pliku format.cs a pjmedia_vid_codec_param mam w pjmedia.cs? wydaje mi się że błąd jest gdzieś w odpowiednim ułożeniu pól w strukturach, jednakże wyeksportowałem już kilka podobnych struktur i nie miałem z nimi takich problemów.

dodam że testowałem co z czym zamienia i oto wyniki

parametr wart. w c++ wart. w c#
dir PJMEDIA_DIR_ENCODING_DECODING PJMEDIA_DIR_ENCODING_DECODING
packing PJMEDIA_VID_PACKING_PACKETS PJMEDIA_VID_PACKING_PACKETS
enc_fmt.det.aud.avg_bps 256000 256000
enc_fmt.det.aud.bits_per_sample 1001 1001
enc_fmt.det.aud.channel_count 480 480
enc_fmt.det.aud.clock_rate 720 720
enc_fmt.det.aud.frame_time_usec 30000 30000
enc_fmt.det.aud.max_bps 512000 512000
enc_fmt.det.user
enc_fmt.det.vid.size.h 480 480
enc_fmt.det.vid.size.w 720 720
enc_fmt.det.vid.fps.denum 1001 1001
enc_fmt.det.vid.fps.num 30000 30000
enc_fmt.det.vid.avg_bps 256000 256000
enc_fmt.det.vid.max_bps 512000 512000
enc_fmt.detail_type PJMEDIA_FORMAT_DETAIL_VIDEO PJMEDIA_FORMAT_DETAIL_VIDEO
enc_fmt.id 859189840 859189840
enc_fmt.type PJMEDIA_TYPE_VIDEO PJMEDIA_TYPE_VIDEO
enc_fmtp.cnt 0 0
enc_mtu 1500 808596553
ignore_fmtp 0 0
packing PJMEDIA_VID_PACKING_PACKETS PJMEDIA_VID_PACKING_PACKETS
dec_fmt.det.aud.avg_bps 3267044 3267044
dec_fmt.det.aud.bits_per_sample 1001 3267044
dec_fmt.det.aud.channel_count 576 30000
dec_fmt.det.aud.clock_rate 720 576
dec_fmt.det.aud.frame_time_usec 30000 1001
dec_fmt.det.aud.max_bps 3267044 2
dec_fmt.det.user
dec_fmt.det.vid.size.h 576 30000
dec_fmt.det.vid.size.w 720 576
dec_fmt.det.vid.fps.denum 1001 3267044
dec_fmt.det.vid.fps.num 30000 1001
dec_fmt.det.vid.avg_bps 3267044 3267044
dec_fmt.det.vid.max_bps 3267044 2
dec_fmt.detail_type PJMEDIA_FORMAT_DETAIL_VIDEO 720
dec_fmt.id 808596553 2
dec_fmt.type PJMEDIA_TYPE_VIDEO PJMEDIA_TYPE_VIDEO
dec_fmtp.cnt 2 3
param[0].name.ptr CIF 1
param[1].name.ptr QCIF 1
param[2].name.ptr

P.S.
Jak wkleić w przyszłości taki adres strony z podwójnymi 'podłogami' aby wyglądał jak url, a nie obcinał?

1 użytkowników online, w tym zalogowanych: 0, gości: 1