Gå til innhold

C#: Tilgang til C++dll via C#. Noe spørsmål


Anbefalte innlegg

Hei. Skal bruke en C++ dll fra C#. Tidligere har jeg gjort dette gjennom

1.

COM som blir omtrent som å bruke en C# dll er mitt inntrykk

eller

2.

F.eks noe slik som dette

[DllImport("filnavn.dll")]

public static extern void Start();

 

Problemet mitt er att det ikke er en COM komponent samt metodene ligger jo her i klasser. Og tror ikke den kan aksesseres gjennom metoder deklarert i DEF fil.

 

Dllen jeg har tilgang til har forøvrig vedlagt header filer for de klassene jeg er ute etter å bruke. Og alle klassenes metoder inneholder kun basisdata(int,double,string etc) og ikke klasser etc.

Har et testprosjekt i C++ som bruker dllén på et vis. Men den bruker den bare på denne måten. Klassen som er referert under ligger i header filen. men det rare for meg som kommer med C# bakgrunn er at den ikke instansieres før bruk.

 

Klassenavn k;
int returverdi=k.Load("filnavn");
if(returverdi<0)
(
//Gi Feilmedling
)
etc.
etc.

 

Har hørt et par plasser at jeg kan skrive en wrapper i C++(har ikke koden til dllen. Bare header filene). Gjøre denne COM kompatibel og bruke denne fra C#. Dette er nødløsning om jeg ikke har mulighet til å bruke C# direkte.

 

Kommer med mye rar informasjon og mye rare spørsmål her sikkert :ermm: Men håper noen skjønner hva jeg er ute etter og kan gi meg hjelp med dette.

 

Kan også sies at dllen det er snakk om er et innkjøpt dll som en del av et API. Men vet ikke om det er mulig og evt hvordan denne kan brukes fra C#.

Lenke til kommentar
Videoannonse
Annonse

C# støtter ikke C++ ABI (som svært få, hvis noen andre språk enn C++ gjør)

Det eneste reelle alternativet ditt er å skrive en C++/CLI wrapper. Det denne gjør, er å lage .NET klasser som wrapper rundt alle native funksjoner. Vær dog obs på at det er noen ting en bør være klar over:

C++/CLI = C++ + .NET

Du må lære en ny C++ dialekt som inneholder en del nøkkelord som brukes for kompilering til CIL kode. Du må være obs på garbage collection og hvordan dette fungerer i .NET.

 

Det er ikke så vanskelig når en lærer seg det.

Lenke til kommentar

Takker så masse! :thumbup:

 

Skal se nærmere på dette i morgen. Ikke umulig at her tikker inn et par nye spørsmål i løpet av morgendagen :)

 

Håpte å unngå denne varianten da jeg ikke er helt stø på denne type C++ programmering :) Men satser på min venn Google gir en hjelpende hånd :p

Lenke til kommentar

Hei. Bare et lite oppfølgingsspørsmål for et som ikke er ALTFOR bevandret i C++ :)

 

Et lite utdrag fra eksempelkoden jeg har fått i C++ for APIet:

 

#include "stdafx.h"

#include "ResultAPI.h"
#include "TerrainResultAPI.h"

int _tmain(int argc, _TCHAR* argv[])
{
 std::wstring sProject = L"..\\data\\kursv2\\kursv2-1";

 CResultAPI aResultAPI;
 int iStat = aResultAPI.Open(sProject);
 if (iStat < 0)
 {
    // error opening project
   aResultAPI.Close();
 	return -1; 
 }
aRoadResultAPI.SetSectionSelection(iAPI_SECTION_ALL);
etc
etc

 

Hvordan kan aResultAPI brukes uten å instansieres. Det er det jeg ikke helt skjønner. Og hvordan vil dette fungere om jeg skriver en wrapper slik du nevnte. Eksempelet over bryter med alt jeg har lært om både C++ og C#. Dette ser ikke ut som noe objektorientert ut i det hele tatt. Bare en deklarasjon som blir brukt?

Lenke til kommentar

Mulig løsning på spørsmålet over. Har ikke noen spes kjennskap til header filer. Men kan det være slik at f.eks. inkluderingen av ResultAPI.h gjør at klassen for denne header filen(kjenner ikke innholdet i implementasjons filen) bli instansiert når jeg inkluderer header filen? Da blir jeg litt klokere her :)

 

I så fall. Hvordan vet header filen hvilken dll den skal laste? Dllen ligger i programområdet forøvrig. Scanner den bare alle klasser og finner en som implementerer den nevnte headeren? Hva hvis der er flere klasser som implementerer innholdet i headeren ?

 

Fremdeles endel rare spørsmål her men jobber meg videre :)

Lenke til kommentar

Du burde kunne C++ relativt godt før du begynner å kikke på C++/CLI.

C++ bruker noe som kalles en preprocessor. Det vil si i praksis at dokumentet blir behandlet av en egen compiler kalt en preprocessor før koden som preprocessoren har behandlet blir sendt til C++ compileren. Dette er ikke helt presist, men nok til å få en forståelse av hva som skjer. Når det står #include så vil en fil mer eller mindre bli klippet inn i den endelige koden. Dersom en header fil blir inkludert flere ganger, får du en feilmelding på at elementer er definert flere ganger. Dette bruker #pragma once eller #ifdef EN_HEADER_FIL til å hindre.

 

For å inkludere dll-filer må du typisk ha både en .h fil og en .lib fil.

 

Merk at C++ skiller seg betraktelig fra C# på veldig mange måter.

Lenke til kommentar

Hei. Takker for svar!

 

Dessverre kan jeg ikke C++ veldig godt men håper det er tilstrekkelig til å gjøre det jeg må gjøre for å få hente ut endel data gjennom C++ APIet.

 

Er faktisk nesten i mål i forhold til å kunne greie det jeg må oppnå. Så om jeg hadde fått litt hjelp med å forstå koden under hadde dette vært supert!

 

Greier å kommunisere med Native C++ dll'en fra C# via en C++ CLI wrapper. Dette skal jeg gjøre hele veien for alle klassene. Så da er jeg nesten i mål.

 

Det jeg ikke skjønner er dette.

 

#include "stdafx.h"
#include "RoadResultAPI.h"
#include "VipsIntf\VipsIntf.h" // Road Model Input main class
#include "VipsIntf\BRoBens.h"  // Bed Rock Bench / Rock Shelf
#include "VipsIntf\SurfNos.h"  // Road Model Input Surface Description
#using <mscorlib.dll>
using namespace System;

public ref class CqBedRockBenchsWrapper
{
private:	

public:

int Test()
{
	CqBedRockBenchs aBedRockBench;
	aBedRockBench.Read(1);
	int retur= aBedRockBench.First();
	return retur;
}


int First()
{
	CqBedRockBenchs aBedRockBench;
	int retur= aBedRockBench.First();
	return retur;
}

int Read()
{
	CqBedRockBenchs aBedRockBench;
	aBedRockBench.Read(1);
	return retur;
}
};

 

(Har lastet opp data tidligere via en annen Wrapper klasse som kjører et load kall)

 

  1. Hvordan kan aBedRockBench brukes uten å være instansiert? Ser i debugger at den er klar. nesten som om den er instansiert...
  2. Hvordan ligger dataene klare i aBedRockBench når den ikke er fyllt opp fra noe plass. Utover at jeg har kjørt load metoden i en annen API klasse.
  3. Hver gang jeg kjører CqBedRockBenchs aBedRockBench; nullstilles aBedRockBench. Dette gjør at metoden test fungerer fint. men dersom jeg kjører dette via 2 metoder(via C#) First og Read. noe jeg ønsker så blir aBedROckBench nullstillt og First returnerer 0. Dersom jeg gjør begge kallene i samme metoden returneres 1. Disse kallene vil jeg selvsagt beholde 1 til 1.
  4. Greier ikke å deklarere CqBedRockBenchs aBedRockBench globalt. Jeg får da følgende feil:
    Error 2 error C4368: cannot define 'aBedRockBencha' as a member of managed 'CqBedRockBenchsWrapper': mixed types are not supported g:\API\ViaNova\Novapoint Road API\18.00\examples\TestApp_RoadModel_Input\CqBedRockBenchsWrapper.cpp 15 TestApp_RoadModel_Input
    dersom jeg deklarerer den slik
    private:
    CqBedRockBenchs aBedRockBencha;

 

(begynner å mistenke at dataene ligger i common blokker i Fortran. Uten at jeg kan noe mer om dette kan kanskje dette være en interessant opplysning for den som ser problemet her)

Lenke til kommentar

Aktiv dag her :)

 

Fikk ting til å fungere nå men ikke skjønner fremdeles ikke oppførselen beskrevet i forrige innlegg.

 

#include "stdafx.h"

#include "RoadResultAPI.h"
#include "VipsIntf\VipsIntf.h" // Road Model Input main class
#include "VipsIntf\BRoBens.h"  // Bed Rock Bench / Rock Shelf
#include "VipsIntf\SurfNos.h"  // Road Model Input Surface Description

#using <mscorlib.dll>
using namespace System;

public ref class CqBedRockBenchsWrapper
{
private:	

	CqBedRockBenchs * aBedRockBench;


public:

	CqBedRockBenchsWrapper() { aBedRockBench = new CqBedRockBenchs();}


int Read()
{
	int retur= aBedRockBench->Read(1);
	return retur;
}

osv.

Lenke til kommentar

  1. Hvordan kan aBedRockBench brukes uten å være instansiert? Ser i debugger at den er klar. nesten som om den er instansiert...
  2. Hvordan ligger dataene klare i aBedRockBench når den ikke er fyllt opp fra noe plass. Utover at jeg har kjørt load metoden i en annen API klasse.
  3. Hver gang jeg kjører CqBedRockBenchs aBedRockBench; nullstilles aBedRockBench. Dette gjør at metoden test fungerer fint. men dersom jeg kjører dette via 2 metoder(via C#) First og Read. noe jeg ønsker så blir aBedROckBench nullstillt og First returnerer 0. Dersom jeg gjør begge kallene i samme metoden returneres 1. Disse kallene vil jeg selvsagt beholde 1 til 1.
  4. Greier ikke å deklarere CqBedRockBenchs aBedRockBench globalt. Jeg får da følgende feil:
    Error 2 error C4368: cannot define 'aBedRockBencha' as a member of managed 'CqBedRockBenchsWrapper': mixed types are not supported g:\API\ViaNova\Novapoint Road API\18.00\examples\TestApp_RoadModel_Input\CqBedRockBenchsWrapper.cpp 15 TestApp_RoadModel_Input
    dersom jeg deklarerer den slik
    private:
    CqBedRockBenchs aBedRockBencha;

1. C++ instansierer native code funksjoner dersom du skriver de slik. Default constructor blir kalt.

2. Se 1.

3. Fordi du instansierer variabelen hver gang funksjonskallene utføres (men dette ser det ut til at du har fikset)

4. Også fikset ser det ut til

 

Det er svært viktig å være klar over pekere i C++. Hvis du ikke har * eller ^ foran et variabelnavn blir objektet allokert på stack og instansiert med default constructor (hvis noen) Dersom klassen ikke har noen default constructor, så vil innholdet være vilkårlig, og bør fylles ut manuelt.

 

^ brukes for .NET objekter (ref class)

* brukes som pekere til vanlige C++ verdier.

Lenke til kommentar

Ser ut til at jeg sakte men sikkert kommer meg videre her. Får ut dataene jeg trenger så må bare takke masse for hjelp :thumbup:

Ikke alltid så lett å spørre når en ikke helt ved hva en skal spørre om men begynner å våkne noen sovende C++ hjerneceller her nå :D

Lenke til kommentar

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