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

[C#] c/front koppeling

Pagina: 1
Acties:
  • 672 views sinds 30-01-2008
  • Reageer

  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:11
Sinds 2 weken ben ik bezig geweest om een query-tool te maken om data te gebruiken uit een navision database(native). Zo'n tool kan connectie maken via c/front en odbc. Ik heb hier een reference guide voor c/front in c++ en natuurlijk de cfront.dll.
ik ben begonnen met een kleine opzet dwz ff rustig connectie maken, kijken welke tabellen erzijn, data ophalen etc. Dit allemaal via een listbox voor de resultaten, console.writeline voor waar hij de functies ingaat, en een editbox voor mijn commands.
(navision 3.60, driver is 3.70, code gemaatk in visual c# .net)

Het is me gelukt om:
-connectie te maken en te disconnecten
-Tabellen opvragen
-de velden van een tabel opvragen

Maar ik zit nu bij de records op te vragen. Het lukt me niet op waardes te vragen en in een array/string te zetten.
dll inlaad stukje
code:
1
2
[DllImport("cfront.dll", CallingConvention = CallingConvention.Cdecl)] 
         private static extern int DBL_GetFieldData( string dst, int dstsize, int hTable, int hrecord, int fieldnr);


htable is een pointer naar de tabel en hrecord een pointer naar de record.

dit is het gedeelte van de parser:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
case "lr" : //list records
    int hrecord = DBL_AllocRec(htable);
    DBL_InitRec(htable, hrecord);
    string s = "temp string";
                            
    if (DBL_FindRec(htable, hrecord ,"-") )
    {
        int j = DBL_GetFieldData(s,100,htable, hrecord,1); //j is het aantal bytes van de data
        Result.Add(Convert.ToString(j) + s);

        Console.WriteLine("eerste record gevonden");
    };
    DBL_FreeRec(record);
    break;

Wat hij returned is: "4 temp string". Dus de functie werkt maar de waarde wordt niet in s gezet.

Volgens de reference is de 1e parameter een void*. Dit betekend dat hij alles kan returnen, alleen hoe vang ik dat op in C#?
In de reference staat een voorbeeldje in c++ met deze void* en geeft als 1e een char array mee, dus:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
case "lr" : //list records
    int hrecord = DBL_AllocRec(htable);
    DBL_InitRec(htable, hrecord);
    char[] s = new char[100];
                            
    if (DBL_FindRec(htable, hrecord ,"-") )
    {
        int j = DBL_GetFieldData(s,100,htable, hrecord,1);
        for (int k = 0 ; k < 100 ; k++) 
        {
            temp = temp + s[k];
        }

        Result.Add(Convert.ToString(j) + temp);

        Console.WriteLine("eerste record gevonden");
    };
    DBL_FreeRec(record);
    break;

geeft terug "4". Weederom geen data.

omdat de 1e parameter een in/out variable is heb ik ipv s, ref s gebruikt. Dit bij beide voorbeelden geen succes.
bij voorbeeld 1:
code:
1
2
3
An unhandled exception of type 'System.NullReferenceException' occurred in csharptest.exe

Additional information: Object reference not set to an instance of an object.

bij voorbeeld 2:
code:
1
2
3
An unhandled exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in csharptest.exe

Additional information: Can not marshal parameter #1: Ansi char arrays can not be marshaled as byref or as an unmanaged-to-managed parameter.


Heeft iemand welles met de SDK van Navision gewerkt of een eenzelfde probleem ondervonden met void* en heeft hiervoor tips/oplossing?

[ Voor 4% gewijzigd door PoweRoy op 06-02-2006 13:54 ]

[This space is for rent]


Verwijderd

Ik denk dat je dit beter op de MiBuSo site kunt vragen ( site met gebruikers en developersvragen voor Navision ). http://www.mibuso.com

  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:11
Verwijderd schreef op maandag 06 februari 2006 @ 14:07:
Ik denk dat je dit beter op de MiBuSo site kunt vragen ( site met gebruikers en developersvragen voor Navision ). http://www.mibuso.com
Daar heb ik het hele forum doorgespit maar helaas geen antwoord gevonden, daarom vroeg ik me af of er hier mensen zijn die een oplossing weten.

(hier mijn topic op mibuso)

[This space is for rent]


Verwijderd

hmmm, ik heb jammer genoeg geen ervaring met C/Front ( wel met navision zelf ).
Maar volgens mij zie ik je nergens een specifieke tabel openen ?

  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:11
klopt, die staat al open (de htable is de referentie naar t adres)
code:
1
2
3
4
5
6
7
8
9
10
11
case "ot" : //open table
                    if (query != "")
                    {
                        if (DBL_OpenTable(ref htable, Convert.ToInt32(query)) != 1)
                        {
                            Console.WriteLine("open table " + query + "failed");
                        }
                        else result.Add(query +" opened. " + Convert.ToString(DBL_RecCount(htable)) + " records found");
                    }
                    else result.Add("geen table opgegeven");
                    break;

[This space is for rent]


Verwijderd

Sorry, dan weet ik het verder ook niet meer.

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

eerst en vooral zou ik van het type IntPtr gebruik gaan maken ipv int. Dit maakt de code ook meteen portable.

in realiteit is dit een pointer in (un)managed code.
Bovendien zou ik het stukje over consuming unmanaged dll functions eens lezen.
http://msdn.microsoft.com...UnmanagedDLLFunctions.asp
en dan met betrekking tot marshalling van data
http://msdn.microsoft.com...atawithplatforminvoke.asp

dit zou je zeker op weg moeten helpen over wat je moet doen met die IntPtr etc

ASSUME makes an ASS out of U and ME


  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:11
de IntPtr heb ik al bij een andere functie gebruikt (vond de use op mibuso)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
case "fc" : //list the fields of the specified table
                    if (query != "") 
                    {
                        int i = DBL_NextField(htable,0); //first field
                        Console.WriteLine(DBL_FieldName(htable,1).ToString());
                        while ( i != 0 )
                        {
                            //werkt behalve FieldType :(
                            result.Add( Convert.ToString(i) + " : " 
                                        + Marshal.PtrToStringAnsi(DBL_FieldName(htable,i)));
                                        //+ Convert.ToString(DBL_FieldType(htable,i))); fieldtype werkt niet, krijg getallen terug, als ik marshall krijg ik helemaal niks terug
                            i = DBL_NextField(htable,i);
                        }
                    }
                    else result.Add("geen table opgegeven");
                    break;

Dit werkt

maar als ik
code:
1
2
[DllImport("cfront.dll", CallingConvention = CallingConvention.Cdecl)] 
         private static extern int DBL_GetFieldData( IntPtr dst, int dstsize, int hTable, int record, int fieldnr);

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
case "lr" : //list records
                    int record = DBL_AllocRec(htable);
                    //DBL_InitRec(htable, record); niet nodig alleen bij het veranderen invoegen record
                    IntPtr s = new IntPtr();
                            
                    if (DBL_FindRec(htable, record ,"-") )
                    {
                        
                        int j = DBL_GetFieldData(s,100,htable, record,1);
                        Console.WriteLine(Convert.ToString(j)+Marshal.PtrToStringAnsi(s));

                        Console.WriteLine("findrec gelukt");
                    }; 
                    break;

krijg ik helaas een
code:
1
2
3
An unhandled exception of type 'System.NullReferenceException' occurred in csharptest.exe

Additional information: Object reference not set to an instance of an object


Ik neem aan dat je bedoelde met IntPtr de eerste parameter, want de return waarde is een int en die krijg ik goed terug (as far as i know mbt goed :P)

[ Voor 10% gewijzigd door PoweRoy op 07-02-2006 11:58 ]

[This space is for rent]


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

ik "denk" dat de functie in C++ style van deze vorm is:

C++:
1
2
3
4
5
// void* ptr en size_t size: door de programmeur gealloceerd stuk geheugen waarin de data komt.
// table* htable: pointer naar je table object
// int record en fieldr: indices van de record en field
// return waarde = aantal bytes effectief geschreven.
size_t DBL_GetFieldData(void* ptr, size_t size, table* htable, int record, int fieldnr)


ik kan me dus inbeelden dat jouw code een NULL exceptie geeft binnen de DBL_GetFieldData aangezien die IntPtr op IntPtr.Zero geinitialiseerd wordt en je dus de opdracht geeft om op adres 0 te schrijven.

Je zal dus moeten geheugen moeten zien te alloceren.
Bij het bladeren door de link die ik je gaf kom ik dit tegen:
When a System.Text.StringBuilder is passed by value, the marshaler passes a reference to the internal buffer of the StringBuilder directly to the caller. The caller and callee must agree on the size of the buffer. The caller is responsible for creating a StringBuilder of adequate length. The callee must take the necessary precautions to ensure that the buffer is not overrun. StringBuilder is an exception to the rule that reference types passed by value are passed as In parameters by default. It is always passed as In/Out.
Je zou dit dus eens kunnen proberen met een StringBuilder waarvan je een bepaalde grootte hebt gereserveerd.
Dit geeft als bijkomend voordeel dat je nadien de buffer gemakkelijk kunt bewerken.

ASSUME makes an ASS out of U and ME


  • PoweRoy
  • Registratie: April 2002
  • Laatst online: 20:11
_/-\o_ HIGHGuY _/-\o_

Ik heb het werkend :) heel erg bedankt. Meanwhile had ik verder gezocht in de reference en vond DBL_GetFieldDataAdd, die returned de pointer naar de waarde. Dmv Marshal heb ik die waarde kunnen omzetten, maar dit is natuurlijk mooier!

nu ga ik proberen de data ff om te gooien omdat de data die ik terug krijg uit een code veld formaat pascal is (bij de rest geen probleem :? )
"/4""blaat" 1e byte is dus de lengte. (bij c is het "blaat""\0")

bij waardes uit een type 'code' veld krijg ik bij getallen een blokje ervoor (ascii(of uni) waarde 4 en bij tekst in 'code' veld krijg ik een y met 2 puntjes erop(waarde 255) ervoor

nu dit ff nog uitvogelen

thx highguy!

[ Voor 12% gewijzigd door PoweRoy op 08-02-2006 14:14 ]

[This space is for rent]


  • dick11
  • Registratie: Juni 2005
  • Laatst online: 08-01 07:36
Is het nog gelukt? Bericht is al aardig oud.

Geef anders ff een seintje.


k denk niet dat je het leuk vind als je binnenkort hopen spam binnenkrijgt, dus ik heb maar ff je mail-adres verwijderd. Het doel v/h forum gaat trouwens ook verloren als iedereen mbhv mail met elkaar begint te communiceren.
Ik heb ook de URL naar je website verwijderd, aangezien dat als spam wordt aanzien. Je kan wel je url in je signature plaatsen.

[ Voor 94% gewijzigd door whoami op 14-04-2007 23:15 ]

Dick van der Sar


Verwijderd

dick11 schreef op zaterdag 14 april 2007 @ 18:44:
Is het nog gelukt? Bericht is al aardig oud.
PoweRoy schreef op woensdag 08 februari 2006 @ 13:55:
Ik heb het werkend :) heel erg bedankt.
Pagina: 1