Skinney Skrevet 1. april 2010 Del Skrevet 1. april 2010 Hei! Jeg fant et kort og greit program på weben for komprimering av Strings. Problemet er at det er skrevet i C og ikke C#. Finnes det noen måte å få koden til å fungere med programmet mitt på? Lenke til kommentar
GeirGrusom Skrevet 1. april 2010 Del Skrevet 1. april 2010 To metoder: 1. Skriv om C koden til tilsvarende C# (sannsynligvis den beste løsningen) 2. Kompiler programmet som en .dll fil og bruk DllImport Lenke til kommentar
Skinney Skrevet 1. april 2010 Forfatter Del Skrevet 1. april 2010 Hvordan kompilerer jeg C om til DLL? :S Lenke til kommentar
GeirGrusom Skrevet 1. april 2010 Del Skrevet 1. april 2010 Vel... to ting du må tenke på: calling convection og export library. Calling convection er stdcall i Windows (og C#) men C bruker cdecl. Eksempel: C kode kompileres til hello.dll med Visual C++ extern "C" { __declspec(dllexport) void __stdcall HelloStr(char* outp, int maxlen) { strcpy(outp, "Hello World!", maxlen); } } C#: public static class Imports { [system.Runtime.InteropServices.DllImport("hello")] public static extern void HelloStr(byte[] outp, int maxlen); } Lenke til kommentar
TheMaister Skrevet 2. april 2010 Del Skrevet 2. april 2010 Hvordan er det å benytte seg av C headere i C#? (hvis det i det hele tatt går.) F.eks, hvis man har en funksjon av typen, og må jobbe med en foo_t struct. foo_dothis(foo_t *foo, int bar); Lenke til kommentar
GeirGrusom Skrevet 2. april 2010 Del Skrevet 2. april 2010 Du må oversette headeren. Det finnes sikkert verktøyer for å gjøre dette på internett, ettersom det er en temmelig enkel og rett frem sak. Hvis ikke, så er det ikke stress å gjøre det selv. Ofte kan du bruke notepad og find/replace for å gjøre dette, men det krever at du forstår både C og C# godt. Lenke til kommentar
Skinney Skrevet 2. april 2010 Forfatter Del Skrevet 2. april 2010 Okay, da var jeg kommet ett skritt lengre, men er fortsatt ikke helt i mål. Trur jeg har klart å lage Dll-fila og importere den riktig med denne koden: [DllImport("Smaz.dll")] public static extern int smaz_compress(IntPtr instring, int inlen, IntPtr outstring, int outlen); Har altså bytta ut char* med IntPtr her, som jeg mener skal være riktig. (får jo feil hvis jeg prøver å bruke char* i C#). Problemet kommer når jeg prøver å gjøre om String til IntPtr tror jeg... IntPtr i = Marshal.StringToHGlobalUni(Text); IntPtr o = new IntPtr(); Compress.smaz_compress(i, 1024, o, 1024); return Encoding.UTF8.GetBytes(o.ToString()); Får en MemoryAllocationError eller noe i den dur, sier at den prøver å skrive til protected memory og at dette er et tegn på at minnet er korrupt. Er det noe jeg gjør feil her? Lenke til kommentar
GeirGrusom Skrevet 3. april 2010 Del Skrevet 3. april 2010 Hvis inndata er en char* så kan du benytte vanlig .NET string, så skal .NET konvertere riktig for deg. Eventuelt kan du bruke byte[] istedet så slipper du all Marshal greier. Lenke til kommentar
Skinney Skrevet 4. april 2010 Forfatter Del Skrevet 4. april 2010 Merkelig... Brukte vanlig string istedenfor IntPtr som du sa, men får fortsatt samme feil :S Lenke til kommentar
GeirGrusom Skrevet 5. april 2010 Del Skrevet 5. april 2010 (endret) Fnodig. Du kan se om noen av MarshalAs attributtene kan hjelpe, men jeg tviler. Allokerer biblioteket minnet du får tilbake? Hvis ikke, må du sannsynligvis allokere det for den. Bruk Marshal.AllocHGlobal for dette. Edit: hvis bbiblioteket gjør det, så har biblioteket også funksjoner for å frigjøre, ettersom en bit som er mallocet i en .dll kan ikke free-es av en annen .dll eller .exe. Endret 5. april 2010 av GeirGrusom Lenke til kommentar
Skinney Skrevet 6. april 2010 Forfatter Del Skrevet 6. april 2010 Ok, fant ut at biblioteket ikke allokerte minnet for meg, så jeg brukte AllocHGlobal som du sa, still no luck... Koden ser nå sånn ut: protected override byte[] EncodeData() { IntPtr stringToCompress = Marshal.StringToHGlobalUni(Text); IntPtr compressedString = new IntPtr(1024); Marshal.AllocHGlobal(stringToCompress); Marshal.AllocHGlobal(compressedString); Compress.smaz_compress(stringToCompress, Text.Length, compressedString, Text.Length*2); return Encoding.UTF8.GetBytes(compressedString.ToString()); } Skjønner ikke dette... Lenke til kommentar
GeirGrusom Skrevet 6. april 2010 Del Skrevet 6. april 2010 Marshal.AllocHGlobal(stringToCompress); Marshal.AllocHGlobal(compressedString); må vel være feil? Lenke til kommentar
Skinney Skrevet 6. april 2010 Forfatter Del Skrevet 6. april 2010 Må slutte å programmere etter sengetid Du hadde selvfølgelig rett, og nå fungerer det som fjell! Tusen hjertelig takk for hjelpa For de som er interessert, koden er nå: protected override byte[] EncodeData() { IntPtr stringToCompress = Marshal.AllocHGlobal(Strings.Length); IntPtr compressedString = Marshal.AllocHGlobal(Strings.Length*2); Compress.smaz_compress(stringToCompress, Strings.Length, compressedString, Strings.Length * 2); return Encoding.UTF8.GetBytes(compressedString.ToString()); } Lenke til kommentar
GeirGrusom Skrevet 6. april 2010 Del Skrevet 6. april 2010 Husk å frigjøre minne allokert med AllocHGlobal før funksjonen avslutter Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå