Gå til innhold

Anbefalte innlegg

Skrevet

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å?

Videoannonse
Annonse
Skrevet

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);
}

Skrevet

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);

Skrevet

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.

Skrevet

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?

Skrevet

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.

Skrevet (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 av GeirGrusom
Skrevet

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...

Skrevet

Må slutte å programmere etter sengetid :p

 

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());
       }

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 konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...