01. november 2004 - 17:54
Der er
15 kommentarer og 1 løsning
Anvendelse af C++ med unsigned char pointer pointer pointer
Hej Jeg har en dll fra C++ som jeg skal anvende med en DllImport. Jeg skal anvende en funktion fra dll'en MyFunc() som også er fint nok.Problemet er at den returner en værdi der er lavet med typedef i c++: typedef unsigned char*** val Så den værdi jeg får tilbage er i c++ en unsigned char*** hvilket må være en pointer til et 2D byte array i C#, men hvordan koder man det? har prøvet diverse med byte[,] hvor jeg beskrev at funktionen i C# returnerede en IntPtr men uden held. Nogle der har forslag?
Annonceindlæg fra Barco
01. november 2004 - 19:52
#1
Prøv med (ikke testet) unsafe { [DllImport("din.dll")] public extern static void MyFunc(byte *** ptrVal); } Jeg bruger byte fordi en char er 16 bit (Unicode) i C#.
01. november 2004 - 19:55
#2
Simpelt eksempel. C++ DLL kode: #include "stdafx.h" #include "PtrPtrPtr.h" BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } char *p1 = "A"; char *p2 = "BB"; char *p3 = "CCC"; char *p4 = "DDDD"; char *p5 = "EEEEE"; char *p6 = "FFFFFF"; char *pp1[] = { p1, p2, p3 }; char *pp2[] = { p4, p5, p6 }; char **ppp[] = { pp1, pp2 }; PTRPTRPTR_API char ***ptrptrptr(void) { return ppp; } C# kode: using System; using System.Runtime.InteropServices; class MainClass { [DllImport("D:\\IDEProjects\\VisualStudio\\PtrPtrPtr\\Release\\PtrPtrPtr.dll")] private static extern IntPtr ptrptrptr(); public static void Main(string[] args) { IntPtr ppp = ptrptrptr(); IntPtr pp1 = Marshal.ReadIntPtr(ppp, 0); IntPtr pp2 = Marshal.ReadIntPtr(ppp, 4); IntPtr p1 = Marshal.ReadIntPtr(pp1, 0); IntPtr p2 = Marshal.ReadIntPtr(pp1, 4); IntPtr p3 = Marshal.ReadIntPtr(pp1, 8); IntPtr p4 = Marshal.ReadIntPtr(pp2, 0); IntPtr p5 = Marshal.ReadIntPtr(pp2, 4); IntPtr p6 = Marshal.ReadIntPtr(pp2, 8); string s1 = Marshal.PtrToStringAnsi(p1); string s2 = Marshal.PtrToStringAnsi(p2); string s3 = Marshal.PtrToStringAnsi(p3); string s4 = Marshal.PtrToStringAnsi(p4); string s5 = Marshal.PtrToStringAnsi(p5); string s6 = Marshal.PtrToStringAnsi(p6); Console.WriteLine(s1 + " " + s2 + " " + s3 + " " + s4 + " " + s5 + " " + s6); } }
01. november 2004 - 19:57
#3
C# koden kan naturligvis skrives lidt pænere med for løkker: using System; using System.Runtime.InteropServices; class MainClass { [DllImport("D:\\IDEProjects\\VisualStudio\\PtrPtrPtr\\Release\\PtrPtrPtr.dll")] private static extern IntPtr ptrptrptr(); public static void Main(string[] args) { IntPtr ppp = ptrptrptr(); for(int i = 0; i < 2; i++) { IntPtr pp = Marshal.ReadIntPtr(ppp, 4*i); for(int j = 0; j < 3; j++) { IntPtr p = Marshal.ReadIntPtr(pp, 4*j); string s = Marshal.PtrToStringAnsi(p); Console.WriteLine(s); } } } }
01. november 2004 - 20:13
#4
Eller hvis du gerne vil have data ud som bytes: using System; using System.Runtime.InteropServices; class MainClass { [DllImport("D:\\IDEProjects\\VisualStudio\\PtrPtrPtr\\Release\\PtrPtrPtr.dll")] private static extern IntPtr ptrptrptr(); public static void Main(string[] args) { IntPtr ppp = ptrptrptr(); for(int i = 0; i < 2; i++) { IntPtr pp = Marshal.ReadIntPtr(ppp, 4*i); for(int j = 0; j < 3; j++) { IntPtr p = Marshal.ReadIntPtr(pp, 4*j); for(int k = 0; k < (3*i+j+1); k++) { byte b = Marshal.ReadByte(p, k); Console.Write((char)b); } Console.WriteLine(); } } } }
01. november 2004 - 20:14
#5
Puha der kom lidt kode ;), Tror arne_v har gang i noget. Men som jeg har læst er unsigned char i unmanaged en byte i managed. så jeg kunne godt tænke mig at komme ind til at jeg har byte[,] altså 2D byte array at arbejde med. Så jeg fra det første jeg trækker ud vil kunne sige byte[,] array = data[0]..... hvis i kan se hvad jeg mener?
01. november 2004 - 20:18
#6
Men vil du fortolke data som 8 bit integers eller som tekst ? Det sidste eksempel viser hvordan man kan fiske de enkelte bytes ud og du kan ihvertfald hente over i et 2D/3D array hvis det er det du vil.
01. november 2004 - 20:25
#7
Ja jeg vil læse det ud så jeg kan anvende det som integers 8 bit. kigger lige lidt på det forrige du postede. Der er jo et hav af måder at anvende Marshal på og ville gerne undgå selv at skulle hive det hele ud med for-loops
01. november 2004 - 20:32
#8
Med unsafe som foreslået af driis ser det ud som: using System; using System.Runtime.InteropServices; unsafe class MainClass { [DllImport("D:\\IDEProjects\\VisualStudio\\PtrPtrPtr\\Release\\PtrPtrPtr.dll")] private static extern byte ***ptrptrptr(); public static void Main(string[] args) { byte ***ppp = ptrptrptr(); for(int i = 0; i < 2; i++) { for(int j = 0; j < 3; j++) { for(int k = 0; k < (3*i+j+1); k++) { Console.Write((char)ppp[i][j][k]); } Console.WriteLine(); } } } }
01. november 2004 - 20:34
#9
Det ligner det sidste eksempel med IntPtr meget. Det aller vigtigste spørgsmål er om du kender dimensionerne ? Hvis ikke så har du et problem !
01. november 2004 - 21:36
#10
jeg kender dimensionerne. og jeg ved at jeg ved firstArray[0] får et byte[][] array, dog ville jeg blot gerne undgå den unsafe kode i c#
01. november 2004 - 21:40
#11
20:13:07 koden er ikke unsafe.
01. november 2004 - 21:49
#12
Ja ok, for så at trække den helt ud så vil det vel være muligt at hive data ud i byte[,] uden at loope gennem dem alle ....
01. november 2004 - 21:54
#13
Det skulle nok være PtrToStructure så. Jeg kan prøve og få det til at virke.
01. november 2004 - 22:21
#14
Det kan jeg ikke få til at virke. En mulig årag er at char*** ikke er et multidimensionalt array men et array af arrays. b[][][] ikke b[,,]
01. november 2004 - 22:33
#15
Helt ok, smid et svar og så er der point
01. november 2004 - 22:36
#16
svar
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.