[C#] Unmanaged code aanspreken

Pagina: 1
Acties:

  • _Erikje_
  • Registratie: Januari 2005
  • Laatst online: 08:31

_Erikje_

Tweaker in Spanje

Topicstarter
Ik ben een beetje aan het klooien met de InteropService van Microsoft.

De situatie is als volgt:
Ik heb een unmanaged C++ methode gedefinieerd als volgt:
C++:
1
2
//In de header file...
extern "C" __declspec(dllimport) bool blaat( const char* c);

Deze wordt gecompiled tot mijn_dll.dll en dat werkt goed zonder error's.
De methode veranderd de waarde van c. Deze waarde moet in C# weer te gebruiken zijn.

In C# heb ik het volgende staan:
C#:
1
2
[DllImport(mijn_dll.dll)]
unsafe public static extern bool blaat(ref string s);

En deze methode wordt aangeroepen op de volgende manier
C#:
1
2
3
4
public void doeBlaat( string sBlaat )
{
   blaat(ref sBlaat); 
}


Nu krijg ik in doeBlaat bij het aanroepen van blaat(sBlaat) een keiharde herinnering dat ik niet in andermans geheugen mag gaan kloten
code:
1
2
3
An unhandled exception of type 'System.AccessViolationException' occurred in mijnProject.dll

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.


Hoe kan ik op een nette manier mijn const char* methode in C++ aanspreken in C#? Het Internet staat vol met website's over dit maar ik krijg het niet werkend.

  • Daspeed
  • Registratie: Maart 2001
  • Laatst online: 12:17
moet je bij de aanroep ook geen ref zetten?

C#:
1
blaat(ref sBlaat);

  • _Erikje_
  • Registratie: Januari 2005
  • Laatst online: 08:31

_Erikje_

Tweaker in Spanje

Topicstarter
DrClearbottom schreef op donderdag 22 februari 2007 @ 12:11:
moet je bij de aanroep ook geen ref zetten?

C#:
1
blaat(ref sBlaat);
Overtik foutje 8)7

  • Invisible_man
  • Registratie: Juni 2006
  • Laatst online: 10:42
Heb me hier ook wel eens mee bezig gehouden, maar die code heb ik thuis (zit op werk). Maar er staat me iets bij dat je de van het aanroepen tussen "unsafe{ [code] }" moet zetten. Heeft er mee te maken dat C# (oftewel .net) zelf wat omspeelt met het toewijzen van geheugenplaatsen wat het werken met harde pointers onmogelijk maakt. Met unsafe geef je geloof ik (als iemand het beter weet, graag verbeteren :)) aan dat je toegewezen geheugen op de zelfde plek en achter elkaar (in het geval van strings en arrays) moet staan.

  • _Erikje_
  • Registratie: Januari 2005
  • Laatst online: 08:31

_Erikje_

Tweaker in Spanje

Topicstarter
Invisible_man schreef op donderdag 22 februari 2007 @ 12:16:
Heb me hier ook wel eens mee bezig gehouden, maar die code heb ik thuis (zit op werk). Maar er staat me iets bij dat je de van het aanroepen tussen "unsafe{ [code] }" moet zetten. Heeft er mee te maken dat C# (oftewel .net) zelf wat omspeelt met het toewijzen van geheugenplaatsen wat het werken met harde pointers onmogelijk maakt. Met unsafe geef je geloof ik (als iemand het beter weert, graag verbeteren :)) aan dat je toegewezen geheugen op de zelfde plek en achter elkaar (in het geval van strings en arrays) moet staan.
Ja met unsafe mag je met pointers werken. Maar ik krijg nog steeds dezelfde error als voorheen...
Het werken met de DLL werkt ook wel hoor. Maar zodra ik geheugen die ik in C# aangemaakt heb ik C++ ga bewerken geeft ie een error

[ Voor 8% gewijzigd door _Erikje_ op 22-02-2007 12:20 ]


  • Av3ng3rtje
  • Registratie: December 2002
  • Laatst online: 10-11 18:52
misschien heb je hier iets aan:
http://www.codeproject.com/csharp/unmanage.asp

  • _Erikje_
  • Registratie: Januari 2005
  • Laatst online: 08:31

_Erikje_

Tweaker in Spanje

Topicstarter
Nee jammergenoeg niet. Er worden geen referenties meegegeven in deze tutorial

  • Not Pingu
  • Registratie: November 2001
  • Laatst online: 20-11 21:40

Not Pingu

Dumbass ex machina

_Erikje_ schreef op donderdag 22 februari 2007 @ 11:46:
C#:
1
2
3
4
public void doeBlaat( string sBlaat )
{
   blaat(ref sBlaat); 
}
C#:
1
2
3
4
unsafe public void doeBlaat( string sBlaat )
{
   blaat(&sBlaat); 
}


:?

Certified smart block developer op de agile darkchain stack. PM voor info.


  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Zonder alle posts aandachtig te hebben doorgelezen:

Probeer in plaats van een string een StringBuilder instantie mee te geven aan je unmanaged code - dit is in ieder geval wat ik altijd heb gezien als het gaat om bewerken van strings vanuit unmanaged code.

strings zijn nl. immutable in .NET :)

  • Invisible_man
  • Registratie: Juni 2006
  • Laatst online: 10:42
Ok, ik heb het stukje code dat ik ooit gemaakt heb gevonden (een string meegeven aan de functie OnSend in de native dll):

C#:
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
public class TcpCommunicator
{
        [DllImport("socket.dll")]
        public static extern int OnSend(IntPtr itp, int length);

        [DllImport("socket.dll")]
        public static extern int OnDataAvail();

        [DllImport("socket.dll")]
        public static extern IntPtr OnReceive();

        public void SendData(String message)
        {
            byte[] ba = Encoding.ASCII.GetBytes(message);
            unsafe
            {
                fixed (byte* cp = ba)
                {
                    int x = OnSend(new IntPtr(cp), message.Length);
                }
            }
        }


}


Data uit de dll halen bleek wat moeilijker (stukje code wat door een timer om de zoveel tijd uitgevoerd wordt om te kijken of er nieuwe data is binnengekomen via de native dll):

C#:
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
void reccheck_Tick(object sender, EventArgs e)
{
    int datalength = OnDataAvail();
    if (datalength > 0 && this.connected && !this.preclose)
    {
        unsafe
        {
            int x = 0;
            try
            {
                IntPtr ipt = OnReceive();
                String output = "";
                while (x < datalength)
                {
                    byte[] k = new byte[1];
                    k[0] = Marshal.ReadByte(new IntPtr(ipt.ToInt32() + x));
                    char[] c = new char[1];
                    c = Encoding.ASCII.GetChars(k);                                               
                    output += c[0];
                    x++;
                }                      
                this.parent.communicator.DecodeProtocol(output);
            }
            catch
            {
                this.parent.AddMessage("Receive dll error!");
            }
        }
    }
}

[ Voor 5% gewijzigd door Invisible_man op 22-02-2007 20:16 ]


  • _Erikje_
  • Registratie: Januari 2005
  • Laatst online: 08:31

_Erikje_

Tweaker in Spanje

Topicstarter
Op het moment snap ik niet waarom ze Interop wel eens IJW(It Just Works) noemen.

Ik heb een methode
C++:
1
extern "C" __declspec(dllimport) ImgRefPtr bla(int loos, int width, int height, int len, bool forceUnique);

en deze roep ik aan met
C#:
1
2
3
4
//dllImport troep...
unsafe public static extern IntPtr bla(int loos, int width, int height, int len, bool forceUnique);
...Aanroeping:
bla(666, 100, 300, 256, true);// Ik doe iets met de return value

Tijdens debugging geeft hij bij de C++ code gezellig het volgende
code:
1
imageCreateByName(100, 300, 256, 1, false);


Oftewel Microsoft schuift gezellig alle parameters een stapje naar links. Daarom kreeg ik eerder ook die accessviolation error.. :'( ...
Iemand ervaring met het oplossen van dit probleem???

  • /\/\|)
  • Registratie: Juli 2000
  • Laatst online: 21-11 12:02
De term IJW wordt alleen gebruikt voor een bepaald type interop tussen managed C++ en unmanaged C++.

Ik denk dat je de oplossing moet zoeken in de parameters van het DllImport atribuut, bijv. CallingConvention.

  • _Erikje_
  • Registratie: Januari 2005
  • Laatst online: 08:31

_Erikje_

Tweaker in Spanje

Topicstarter
Ik ben er denk ik achter... Je mag waarschijnlijk geen eigen gemaakte objecten returnen... Als ik een bool return type geef dan doet hij het wel...
Pagina: 1