» »

uporaba C++ unmanaged kode v C#.NET projektu

uporaba C++ unmanaged kode v C#.NET projektu

RiNC ::

Torej imam en problem. V C#.NET pišem eno grafično aplikacijo za primerjavo in testiranje različnih grafičnih formatov (PNG, JPEG, JPEG2000, ... ,PGF). V bistvu je ta aplikacija del diplomskega dela...

Podporo za branje/pisanje večine grafičnih formatov sem si zagotovil z uporabo FreeImage knjižnice, ki ima C# wrapper (DLL, ki sem ga vklučil v moj projekt). Problem nastane pri podpori "novega" formata PGF (Progressive Graphics File) ki je glavna tema diplomskega dela. Našel sem libPGF knjižnico, ki pa je v bistvu unmanaged C++ koda, ki je ne morem kar direktno vklučit v moj projekt.

Kaj mi je za naredit? Kako lahko iz te kode dobim DLL?
Po pravici povedano tega še nisem nikoli delal...
Od včeraj zjutraj surfam po netu, tako da me že pošteno boli glava.
Prišel sem do spoznanja da moram nekako napisat wrapper za tole zadevo. Več mi ni jasno...

Prosim za malo pomoči.
CURIOSITY did not kill the cat...
...it was the BUS!

PaX_MaN ::

Morda ti bo tale Q&A pomagal.

RiNC ::

OK, zdaj sem si naredil 2 testna projekta.

Prvi je C++ Win32 DLL projekt, kjer izgleda datoteka SUMtest.cpp takole:

// SUMtest.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"

__declspec(dllexport) int sumAB(int a, int b)
{
	return a + b;
}

...projekt zbildam in dobim SUMtest.dll!
Drugi projekt je C# Windows Forms Application, kjer v Form1.cs izgleda takole:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();  
        }

        [DllImport("SUMtest.dll")]
        static extern int sumAB(int a, int b);

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show(sumAB(4,5).ToString());
        }
    }
}

To sicer še ne dela čisto, vendar se iz tega vidi za kaj se gre.
Moja ideja sedaj je, da bi naredil en C++ Win32 DLL projekt, v katerega vstavim vso kodo iz libPGF knjižnice (vse .h in .cpp datoteke).
Nato si napišem 2 funkciji (encode, decode) in jih exportam na tak način kot sem naredil sumAB v testnem projektu.
Tako dobim delujoči DLL, s pomočjo katerega lahko V C# projektu dostopam do teh dveh funkcij - drugega zaenkrat ne rabim.

Je to res tak "enostavno" kot na prvi pogled zgleda?
Pazit morem seveda na tip funkcije (verjetno z int ali bool ne bom mel problemov).
CURIOSITY did not kill the cat...
...it was the BUS!

noraguta ::

približno tako enostavno. je pa dostikrat kaj poprej še inicializirat. + tega boš moral naredit marshaling za argumente encode ter decode.
Pust' ot pobyedy k pobyedye vyedyot!

RiNC ::

ahm. :(
CURIOSITY did not kill the cat...
...it was the BUS!

noraguta ::

kaj te muči ?
Pust' ot pobyedy k pobyedye vyedyot!

RiNC ::

Ok, sem malo pred tem da bom končal!!! :D
Muči me le še ena stvar...

Tole je funkcija iz DLL-ja:

extern "C" __declspec(dllexport) char* GetColorTypePGF(char* source)
{
	...

	char* colortype = (char*)image->GetColorType();

	CloseHandle(fd);
	delete image;
	return colortype;
}

Tole pa je moj klic funkcije v C# Windows Aplikaciji:

[DllImport("PGFWrapper.dll")]
static extern string GetColorTypePGF(string source);

private void PGFFileInfo()
{
	...

	string colorModel = GetColorTypePGF(source);
	switch (colorModel)
	{
            case "FIC_MINISWHITE":
                labelColorModel.Text = "Gray";
                break;
            case "FIC_MINISBLACK":
                labelColorModel.Text = "Gray";
                break;
            case "FIC_PALETTE":
                labelColorModel.Text = "Indexed";
                break;
            case "FIC_RGB":
                labelColorModel.Text = "RGB";
                break;
            case "FIC_RGBALPHA":
                labelColorModel.Text = "RGBA";
                break;
            case "FIC_CMYK":
                labelColorModel.Text = "CMYK";
                break;
            default:
                labelColorModel.Text = "???";
                break;
	}
}

Problem nastane v vrstici:
string colorModel = GetColorTypePGF(source);

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

GRDA!!! ;((
CURIOSITY did not kill the cat...
...it was the BUS!

PaX_MaN ::

C++ ne poznam najbolje, ampak, a ne vračaš ti pointer na char?
Recimo, tukaj pravi:
AccessViolationException is just a wrapper of the unmanaged access
violation (0xC0000005), caused by a bad pointer.


Pa še dva linka na podobni težavi:
http://social.msdn.microsoft.com/Forums...
http://www.cplusplus.com/forum/windows/...

Jean-Paul ::

Zamenjaj return colortype z return string(colortype) in poskusi razumeti, kje je vzrok za napako.

RiNC ::

Ja, vračam pointer na char.
char* je v bistvu enako kot char[], saj v obeh primerih dobimo pointer na prvi element polja (vsaj kolko se jaz spomnim iz časov ko sem še uporabljal c++).

Bom zdaj malo osvežil znanje, da ugotovim kje sem ga polomil.



Zamenjaj return colortype z return string(colortype) in poskusi razumeti, kje je vzrok za napako.

hmmm. to ne dela.
DLL se prevede, c# program pa krešne!
CURIOSITY did not kill the cat...
...it was the BUS!

Zgodovina sprememb…

  • spremenil: RiNC ()

RiNC ::

Tak je zdaj...
naredil sem tako, da mi funkcija vrača različne int vrednosti, pač moram vedet kaj katera vrednost pomeni.

S prenašanjem stringa iz DLL/Win32 v C#.NET win aplikacijo pa naj se nekdo drugi zajebava.
Meni ni uspelo... :|

Vseeno hvala za pomoč!
CURIOSITY did not kill the cat...
...it was the BUS!

krho ::

static extern string GetColorTypePGF(IntPtr source);
string s = Marshal.PtrToStringAnsi(source)
si.Mail odprto-kodni odjemalec elektronske pošte. - http://www.simail.si
Uredite si svojo zbirko filmov, serij in iger - http://xcollect.sf.net


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Keylogger

Oddelek: Programska oprema
352624 (1351) Blisk
»

kako narediti program ki bere drugi program

Oddelek: Programiranje
465730 (4043) imagodei
»

c++ lib,dll,h za uporabo v C#

Oddelek: Programiranje
91951 (1750) noraguta
»

[c#] naloga za maturo...rabim majhno pomoc

Oddelek: Programiranje
192330 (1667) ql000
»

[C#] unmanaged->managed code

Oddelek: Programiranje
112138 (2013) Zzzzzzz

Več podobnih tem