[C#] AccessViolation door dll functie

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Marc.O
  • Registratie: Maart 2013
  • Laatst online: 03-03-2024
Ik wil in c# een aantal functies uit een dll van derde gebruiken en heb dus geen idee wat de functies onderwater allemaal doen. Zoals het topic al zegt krijg ik een accessviolation exception. Door google ben ik er achter gekomen dat dit meestal optreed door verkeerde pointer waarden maar de functie die ik aanroep krijgt van mij geen pointers mee...

C#:
1
2
3
4
5
6
7
8
[DllImport(@"\lib\onzin.dll", CallingConvention=CallingConvention.Cdecl)]
private static extern int onzin_Connect();
public static string connect()
{
     int result = onzin_Connect();
     if (result == 0) { return result.ToString() + " O.K. Target identified successsfully"; }
     else { return "Error: " + result.ToString(); }
}


Nu is het wel zo dat de dll ook een aantal log/error/warning functies heeft die gebruik maken van een function pointer zodat jezelf de log/error/warning kan verwerken. Aangezien ik niet weet wat de connect functie precies doet denk ik dat dit met de violation te maken kan hebben.

De functies in de dll om deze callbacks te zetten zien er allemaal hetzelfde uit en zijn zo geimplementeerd
C#:
1
2
3
4
5
6
7
8
        public delegate void log_callback(StringBuilder s);
        [DllImport(@"\lib\onzin.dll", CallingConvention=CallingConvention.Cdecl)]
        private static extern void onzin_EnableLog(ref log_callback pfLog);
        public static string enableLog(log_callback pfLog)
        {
            onzin_EnableLog(ref pfLog);
            return "Function executed";
        }


Ik dacht dat het probleem hem misschien nog kon zitten in het feit dat de delgates verplaats worden in het memory door de gc dus deze heb ik met een alloc geprobeerd vast te zetten.
C#:
1
2
3
4
5
6
7
8
       onzinWrapper.log_callback logCb;
        GCHandle gcLog;

        public AppMainForm()
        {
            InitializeComponent();
            gcLog = GCHandle.Alloc(logCb);
        }

gcLog wordt weer vrij gegeven bij het sluiten van het programma.

De enable log functie wordt zo aangeroepen
C#:
1
2
3
4
5
6
7
public void log(StringBuilder s)
{
    txtOutput.Text += "Log: " + s.ToString();
}

logCb = new onzinWrapper.log_callback(log);
onzinWrapper.enableLog(logCb);


Ook dit lost het probleem niet op. Ziet iemand een fout in mijn redenatie of heeft iemand een idee waar het anders nog aan kan liggen?

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Zo zonder header files en een voorbeeld van correct gebruik, of uitgebreide debug info van de access violation, valt hier niet zoveel over te zeggen denk ik. Om dingen vast te zetten zou ik liever fixed gebruiken.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Marc.O
  • Registratie: Maart 2013
  • Laatst online: 03-03-2024
Tja fixed heb ik ook naar gekeken maar ik wil graag een oplossing met safe code.

Er is een c++ voorbeeld programma waar de functies op de volgende marnier gebruikt worden
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef void onzin_LOG (const char* sErr);

onzin_API void onzin_EnableLog (onzin_LOG* pfLog);
onzin_API int onzin_Connect (void);

void _Log(const char *s) {
  printf(s);
  if (*(s + strlen(s) - 1) != '\n') {
    printf("\n");
  }
}

onzin_EnableLog(_Log);
onzin_Connect();

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
log_callback moet gewoon met string (message hoor je niet te veranderen), en ref hoort er niet voor denk ik. En verder kan garbage collection een probleem vormen, afhankelijk van hoe je deze code nu precies gebruikt. Zie MSDN: P/invoke CALLBACK DLL from C#

En in principe is p/invoke natuurlijk nooit echt safe. :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 20:05

Sebazzz

3dp

Let er ook op of je calling convention goed is.

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • Marc.O
  • Registratie: Maart 2013
  • Laatst online: 03-03-2024
Ik heb de StringBuilders verandert naar string. Dit loste het probleem niet op. Verder is de code die ik gebruik net zo opgebouwd als in de link van pedorus.

Ik heb ook alle calling conventions geprobeerd maar als ik andere gebruik krijg ik al eerder PInvokeStackImbalance. Kan het zo zijn dat verschillende functies in een dll verschillende callingconventions hebben?

Edit:
Ik heb een voorbeeld gevonden waarbij de delegate de volgende attribute heeft:
C#:
1
2
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void log_callback(string s);


Dit lijkt het probleem op te lossen.

[ Voor 25% gewijzigd door Marc.O op 18-03-2013 11:44 ]


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
In die link gaat het over stdcall. Werkt het in c++ wel, en is het cdecl? Mogelijk moet dan die delegate anders, zie bijv. http://stackoverflow.com/...ecl-callback-with-pinvoke

Edit: Te lang koffiegedronken, is al opgelost :)

[ Voor 11% gewijzigd door pedorus op 18-03-2013 12:05 ]

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten

Pagina: 1