Laden...

c++ dll in c#

Erstellt von ZeroCool vor 18 Jahren Letzter Beitrag vor 18 Jahren 2.435 Views
Z
ZeroCool Themenstarter:in
16 Beiträge seit 2005
vor 18 Jahren
c++ dll in c#

Hallo Leute,

hab folgendes Problem:

  • muss eine DLL (c++) einbinden (hab ich gemacht)
  • auf die einzelenen Funktionen bzw. Methoden zugreifen (hab ich gemacht)

Mein Problem:
kann den Funktionen Parameter übergeben, nur der rückgabe Parameter liefert eine 0 zurück obwohl er ein 2048 lange zeichenkette zurückliefern sollte.

Main.cs


namespace fCoala
{
    public partial class frm_start : Form
    {
        Coala.coala a = new Coala.coala();
        public frm_start()
        {
            InitializeComponent();            
        }

        private void btn_start_Click(object sender, EventArgs e)
        {            
            a.CoalaMakeTransportKey();
            MessageBox.Show("fertig");
        }
    }
}  

Coala.cs


namespace Coala
{
    public class coala
    {
        long messagelen = 100;

        byte[] jrePath = System.Text.Encoding.ASCII.GetBytes("C:\Programme\Java\jre1.5.0_04");
        byte[] jarPath = System.Text.Encoding.ASCII.GetBytes("C:\Dokumente und Einstellungen\ss\Desktop\Elster_Coala\Teil1_COALA_v3.4.0\Teil1_COALA_v3.4.0\CoalaJavaMethoden\jarFiles_COALA\COALA_fuer_JRE_1.5");
        byte[] message = System.Text.Encoding.ASCII.GetBytes("");
        byte[] transportSchl = System.Text.Encoding.ASCII.GetBytes("");
        byte[] name = System.Text.Encoding.ASCII.GetBytes("Hans");
        byte[] email = System.Text.Encoding.ASCII.GetBytes("Hans@Hans.Hans");
        byte[] producerId = System.Text.Encoding.ASCII.GetBytes("124587");
        byte[] producerVersion = System.Text.Encoding.ASCII.GetBytes("1");
        byte[] locality = System.Text.Encoding.ASCII.GetBytes("Deutschland");
        byte[] country = System.Text.Encoding.ASCII.GetBytes("HH");
        byte[] rCertificate = System.Text.Encoding.ASCII.GetBytes("");
        byte[] rPrivatekey = System.Text.Encoding.ASCII.GetBytes("");

      
        public void CoalaMakeTransportKey()
        {
            int puffer = DLL_Load.CoalaMakeTransportKey(ref rCertificate, ref rPrivatekey, message, ref messagelen, name, email, producerId, producerVersion, locality, country, jrePath, jarPath);
            transportSchl = System.Text.Encoding.ASCII.GetBytes(Marshal.PtrToStringAnsi(puffer));
        }
    }
}  

DLL_LOAD.cs


namespace Coala
{
    public class DLL_Load
    {
        public DLL_Load()
        {
        
        }
        [DllImport("tmCOALA.dll", CharSet = CharSet.Auto)]
        public static extern int CoalaMakeTransportKey(ref byte[] rCertificate, ref byte[] rPrivatekey, byte[] message, ref long messagelen, byte[] name, byte[] email, byte[] producerId, byte[] producerVersion, byte[] locality, byte[] country, byte[] jrePath, byte[] jarPath);   
    }
} 

4.506 Beiträge seit 2004
vor 18 Jahren

Hallo ZeroCool!

Könnte es nicht an folgendem liegen:



public static extern IntPtr CoalaMakeTransportKey(....


Denn das IntPtr ist doch ein Pointer auf ein Integer, oder sehe ich das falsch?

Ich bin bisher GottSeiDank von DLL-Import verschont worden, daher habe ich auch noch keine IntPtr benutzt, aber die Vermutung bleibt trotzdem, dass das das Problem ist.

Ich weiß leider nicht was für ein "Ding" Du für strings benutzen musst (vielleicht "string")?

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

C
192 Beiträge seit 2005
vor 18 Jahren

Also der grund ist in der c++-dll

in c++ kannst du keine Zeichenketten in dem sinn zurückgeben, sondern nur einen Zeiger auf das erste Element der Zeichenkette.

Du wirst also nie eine Zeichenkette erhalten, sondern immer nur eine Zahl, das ist die Adresse auf die der Zeiger zeigt.

Der Wert 0 ist also NULL in c++

debugge mal deine c++-dll und du wirst sehen dass da sowas drinnen steht:

return null;

oder :

char []a; a = NULL;
...
return a;

Bastle erstmal run, und vergewissere nochmal,dass dein c++-Code garantiert einen Zeiger verschieden von 0 zurückgibt, dann erhältst du in c# auch einen wert verschieden von 0

S
8.746 Beiträge seit 2005
vor 18 Jahren

Sieht gut aus, wenn der Puffer ein nullterminierter ANSI-String ist.

Falls es wirklich immer eine 2048-Zeichen langes Feld handelt, kann du auch den Rückgabewert via MarshalAs-Attribute (UnmanagedType.LPArray und SizeConst) als char[2048] definieren. Das sparst du dir das PtrToStringAnsi-Geraffel.

Ist denn der IntPtr bereits Null?

Z
ZeroCool Themenstarter:in
16 Beiträge seit 2005
vor 18 Jahren

Hallo,
das mit dem IntPtr macht nichts kann auch geanu sogut int nehmen.
habe etwas in der dokumentation der dll übersehen.
der rückgabe wert ist nicht enscheident.

Das Problem liegt an dem ref.

int TMCOALA_EXP CoalaMakeTransportkey(charrCertificate, char rPrivatekey, char* message, int* messagelen, const char* Name, usw.)

in rCertificate und in rPrivate wird ein Transportschlüssel geschrieben, aber da es ein zeiger ist kann den ja c++ mithilfe der adresse leicht auslesen aber bei mir in den Variablen steht nur der erste buchstabe von 2048 drin.

weis einer wie man dieses Problem lösen kann??

achso in die dll kann ich nicht gucken geschweige den debuggen

C
192 Beiträge seit 2005
vor 18 Jahren

in c# gibt es eigentlich keine Zeiger und daher hab ich damit in c# noch nicht viel gemacht. Ich kann dazu nur soviel sagen: du musst unsave-blöcke zulassen, das ist in den Projekteinstellungen zu finden. Um dann kannst in solchen Blocken programmieren

...
unsafe
{
... // Mache pointerarithmetik
}

Aber wie gesagt, ich hab noch ncihts mit Zeiger gemacht, google hat mal danach, wie man Zeiger unter c# benutzt bzw. google danach, wie unsafe-Blocke programmiert werden.

Hast du schonmal mit Zeiger in c++ oder c programmiert? Es dürfe in c# so ähnlich sein

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von ZeroCool

in rCertificate und in rPrivate wird ein Transportschlüssel geschrieben, aber da es ein zeiger ist kann den ja c++ mithilfe der adresse leicht auslesen aber bei mir in den Variablen steht nur der erste buchstabe von 2048 drin.

weis einer wie man dieses Problem lösen kann??

Ersetze doch mal deine "ref byte[]" durch string. Du musst allerdings mit MarshalAs die ganze Geschichte auf ANSI biegen.

ref byte[] geht nur dann, wenn du mit MarshalAS eine feste ConstSize angibst (und LPArray).

Mit unsafe brauchst du nicht zu arbeiten.

Z
ZeroCool Themenstarter:in
16 Beiträge seit 2005
vor 18 Jahren

Hier die lösung:


public void CoalaMakeTransportKey()
        {
            int puffer = DLL_Load.CoalaMakeTransportKey( ref rCertificate, ref rPrivatekey, message, ref messagelen, name, email, producerId, producerVersion, locality, country, jrePath, jarPath);
            transportSchl = System.Text.Encoding.ASCII.GetBytes(rCertificate);
        }


und


[DllImport("tmCOALA.dll", CharSet = CharSet.Auto)]
        public static extern int CoalaMakeTransportKey([MarshalAs(UnmanagedType.AnsiBStr)]ref string rCertificate, ref string rPrivatekey, byte[] message, ref long messagelen, byte[] name, byte[] email, byte[] producerId, byte[] producerVersion, byte[] locality, byte[] country, byte[] jrePath, byte[] jarPath);


Hab die lösung deshalb dran gehangen damit andere die lösung auch zu gesicht bekommen. Finde es immer scheiße, wenn machne sagen, das Sie es geschafft haben, aber keinen code freigeben (von der lösung). So wird denjenigen das Leben erschwert die mal das selbe Problem haben

thx @ all

besonders an svenson