Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

[c#] Dllimport kwestie

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik zit hier te vechten met de DllImport in C#. En kom er niet echt aan uit.
Wat is er mis met onze code tags?

Ik heb hiet een C++ dll, en de header file waarin staat beschreven welke functie's exporteerd worden.
Ik wil deze graag vanuit C# aanroepen. Deze dll bestaat uit 5 functies: read, write, open, close, seek.
(dit zijn niet de volledige functie namen trouwens).

Nu kan ik open/close/seek perfect uitvoeren. En begeef me nu in de richting van de read/write fuctie.
vanuit daar geeft hij mij een error:Additional information: Method's type signature is not Interop compatible.

Ik ben vrijwel verzekerd dat dit iets met de buffer te maken heeft die word doorgegeven. Ik weet echter niet wat ik moet doen om het te repareren. Ik heb even geprobeert de Marshall larray door te geven maar dat gaf weinig verbetering.

Graag zou ik willen weten wat ik fout doet en het werkend krijgen dus men ideeen heeft hoor ik ze graag. :)

C++:
1
2
DATAFILEREADERDLL_API __uint ro2data_read ( ro2data_handle *handle,
                __uchar *pBuf,__uint BlockSize,__uint BlockCount );


C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[DllImport("DataFileReaderDll.Dll", 
                EntryPoint = "?ro2data_read@@YAIPAUro2data_handle@@PAEII@Z")]
public extern static uint ro2data_read(out IntPtr handle, out byte[] buffer,
                uint BlockSize, uint BlockCount);


private void Decrypt()
{
    IntPtr handle = new IntPtr();
    if (ro2data_open(out handle, "ChatCommand.dat") == false) return;

    byte buffer = new byte();
    ro2data_read(out handle, out buffer, 4, 4);
    ro2data_close(out handle);
}

[ Voor 28% gewijzigd door een moderator op 09-08-2007 20:08 . Reden: Code integraal in topic opgenomen ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 14:05
We hebben hier code-tags; gebruik die om code te posten ipv een link te plaatsen naar pastebin.
Dat maakt het topic overzichtelijker, en men moet niet 'wegzappen'.

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 14:05
Ben je zeker dat je out parameters moet gebruiken ?

https://fgheysels.github.io/


Verwijderd

Topicstarter
Nou om eerlijk te zijn ik ben niet de maker van de dll dus weet ik niet wat het precies doet. En het staat er ook niet beschreven. Maar mijn ervaring met file functie's zeggen mij dat het betreft om een functie waarbij je de buffer doorgeeft als pointer en de functie in de dll deze opvult.

En in dat geval moet je dus de out parameter gebruiken. En een unsigned char in C++ is een byte in C# dus van een verkeerde type veld ga ik niet vanuit.

Overigens
"Wat is er mis met onze code tags?" leuke edit, maar ik had dit al op pastebin staan. No offense maar ik probeer altijd eerst op irc te vragen voordat ik forums er over vol spam. :)

  • doctormetal
  • Registratie: Februari 2006
  • Laatst online: 28-11 23:07
Je moet die byte array als pointer meegeven. Zie hiervoor het fixed keyword in C#.
Deze moet je zowieso gebruiken omdat je anders leuke acces violations kan krijgen als tijdens je dll call de garbage collector actief wordt.

Verwijderd

Topicstarter
Zo te zien werkt dat, of althans het geeft nu een access voilation error. Ik geeft hem nu door als byte pointer in een unsafe context. Kan je me een voorbeeld geven hoe ik die fixed bytes assignen moet?
Kan dat gedeelte namelijk niet erg duidelijk vinden.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
            IntPtr handle = new IntPtr();
            if (ro2data_open(out handle, "ChatCommand.dat") == false) return;

            byte[] buff = new byte[4];
            unsafe
            {
                fixed (byte* pbuff = buff) ro2data_read(out handle, pbuff, 4, 4);
                foreach (byte b in buff)
                {
                    Console.WriteLine(b);
                }
            }

            ro2data_close(out handle);



Oplossnig gevonden, dank je doctormetal :)

[ Voor 50% gewijzigd door Verwijderd op 09-08-2007 20:52 ]


Verwijderd

Topicstarter
Zoals ik in mijn andere post al omschrijvde voordat die gesloten werd. Ondanks mijn argumenten voor een nieuw topic wel goed waren.

In mijn applicatie kan ik nu files decrypten en encrypten. Echter bij het encrypten heb ik last van een naar foutje. Deze fout houdt in dat wanneer ik de debugger gebruikt ik alles perfect kan encrypten maar zodra ik de applicatie probeert te draaien vanuit mijn bin/release folder krijg ik opeens andere encryptie te voorschijn.

Om het nog een tikkie erger te maken is de encryptie in de standalone ook nog eens iedere keer verschillend. Ik heb een vaag vermoeden dat dit iets te maken hebt met de garbage collector. ik kan dit niet echt onderbouwen, maar een gevoel is een gevoel.

Kort opgesomd:
EXE + Debuger -> Perfect
EXE -> Bagger

Graag zou ik een oplossing zien voor het probleem waar ik ben tegenaangelopen maar ik ben ver door al mijn ideen heen. Ik heb getest of mijn binaire data goed hergebouwd word en dit is ja, ergens bij de dll functies moet het misgaan. :S


De C++ implantatie header
code:
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
// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the DATAFILEREADERDLL_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// DATAFILEREADERDLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
// DataFileReader.dll (C) Ro2Helpers. All rights reserved.
#include <stdio.h>
#ifdef DATAFILEREADERDLL_EXPORTS
#define DATAFILEREADERDLL_API __declspec(dllexport)
#else
#define DATAFILEREADERDLL_API __declspec(dllimport)
#endif

typedef unsigned int __uint;
typedef unsigned char __uchar;

enum ro2data_offset { offset_cur = 1, offset_end = 2, offset_start = 3 };

typedef struct
{
    FILE *hFile;
    __uint fPos;
} ro2data_handle;

DATAFILEREADERDLL_API __uint ro2data_read ( ro2data_handle *handle, 
                                    __uchar *pBuf,
                                    __uint BlockSize,
                                    __uint BlockCount );

DATAFILEREADERDLL_API __uint ro2data_write ( ro2data_handle *handle, 
                                    __uchar *pBuf,
                                    __uint BlockSize,
                                    __uint BlockCount );

DATAFILEREADERDLL_API bool ro2data_open ( ro2data_handle *handle, 
                                    char *name );

DATAFILEREADERDLL_API int ro2data_seek ( ro2data_handle *handle, 
                                int seek, int origin );

DATAFILEREADERDLL_API int ro2data_close ( ro2data_handle *handle );


Mijn C# dll code
code:
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.IO;
using System.Runtime.InteropServices;


namespace Encryption
{
    public static class Program
    {
       

        [DllImport("DataFileReaderDll.Dll", EntryPoint = "?ro2data_open@@YA_NPAUro2data_handle@@PAD@Z")]
        private extern static bool ro2data_open(ref IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] string name);

        [DllImport("DataFileReaderDll.Dll", EntryPoint = "?ro2data_seek@@YAHPAUro2data_handle@@HH@Z")]
        private extern static int ro2data_seek(ref IntPtr handle, int seek, int origin);

        [DllImport("DataFileReaderDll.Dll", EntryPoint = "?ro2data_close@@YAHPAUro2data_handle@@@Z")]
        private extern static int ro2data_close(ref IntPtr handle);

        [DllImport("DataFileReaderDll.Dll", EntryPoint = "?ro2data_read@@YAIPAUro2data_handle@@PAEII@Z")]
        private extern unsafe static int ro2data_read(ref IntPtr handle, byte* buffer, uint BlockSize, uint BlockCount);

        [DllImport("DataFileReaderDll.Dll", EntryPoint = "?ro2data_write@@YAIPAUro2data_handle@@PAEII@Z")]
        private extern unsafe static int ro2data_write(ref IntPtr handle, byte* buffer, uint BlockSize, uint BlockCount);


        public static unsafe string TmpDecrypt(string filename)
        {
            //This functions decrypts a RO2 dat file .... 
            //now this works real easy, the dll at which we link handles our encyption/decryption
            //we just keep on looping till we reach the end of the file and afterwards we replace
            //our file

            #region Assign memory...
            IntPtr handle = new IntPtr();
            string _filename = Path.GetTempFileName();
            string _filename2 = filename;
            byte[] buff = new byte[64];
            bool eof = false;
            int i = 0;
            #endregion

            #region Set up filestreams...
            if (ro2data_open(ref handle, filename) == false) return "";
            FileStream storage = File.Open(_filename, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            #endregion

            #region loop through filelength
            while (eof == false)
            {
                fixed (byte* pbuff = buff) i = ro2data_read(out handle, pbuff, 1, 64);
                storage.Write(buff, 0, i);
                storage.Flush();
                if (i < 64) { eof = false; break; }
            }
            #endregion

            #region Close filestreams
            ro2data_close(out handle);
            storage.Close();
            #endregion

            #region exchange files
            return _filename;
            #endregion
        }

        public static unsafe void Decrypt(string filename)
        {
            //This functions decrypts a RO2 dat file .... 
            //now this works real easy, the dll at which we link handles our encyption/decryption
            //we just keep on looping till we reach the end of the file and afterwards we replace
            //our file

            #region Assign memory...
            IntPtr handle = new IntPtr();
            string _filename = Path.GetTempFileName();
            string _filename2 = filename;
            byte[] buff = new byte[64];
            bool eof = false;
            int i = 0;
            #endregion

            #region Set up filestreams...
            if (ro2data_open(out handle, filename) == false) return;
            FileStream storage = File.Open(_filename, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            #endregion

            #region loop through filelength
            while (eof == false)
            {
                fixed (byte* pbuff = buff) i = ro2data_read(out handle, pbuff, 1, 64);
                storage.Write(buff, 0, i);
                storage.Flush();
                if (i < 64) { eof = false; break; }
            }
            #endregion

            #region Close filestreams
            ro2data_close(out handle);
            storage.Close();
            #endregion

            #region exchange files
            File.Delete(_filename2);
            File.Move(_filename, _filename2);
            #endregion
        }

        public static unsafe void Encrypt(string filename)
        {
            //This functions decrypts a RO2 dat file .... 
            //now this works real easy, the dll at which we link handles our encyption/decryption
            //we just keep on looping till we reach the end of the file and afterwards we replace
            //our file

            #region Assign memory...
            IntPtr handle = new IntPtr();
            string _filename = filename;

            string _filename2 = filename + ".tmp";
            byte[] buff = new byte[64];
            int i = 0;
            #endregion

            #region Set up filestreams...
            File.Create(_filename2).Close();
            if (ro2data_open(ref handle, _filename2) == false) return;
            FileStream storage = File.Open(_filename, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            #endregion

            #region loop through filelength
            unsafe
            {
                while ((i = storage.Read(buff, 0, 64)) > 0)
                {
                    Console.Write(buff);
                    fixed (byte* rbuff = buff) ro2data_write(ref handle, rbuff, 1, Convert.ToUInt32(i));
                }
            }

            #endregion

            #region Close filestreams
            ro2data_close(ref handle);
            storage.Close();
            #endregion

            #region exchange files
            File.Delete(_filename);
            File.Move(_filename2, _filename);
            #endregion
        }
    }
}

[ Voor 93% gewijzigd door Verwijderd op 12-08-2007 15:58 ]

Pagina: 1