Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Export funkcije iz .NET-a

[es] :: .NET :: Export funkcije iz .NET-a

Strane: 1 2

[ Pregleda: 4106 | Odgovora: 35 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

mmix
Miljan Mitrović
Chief Software Architect
Financial Intelligence Software Ltd.
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6050



+4631 Profil

icon Re: Export funkcije iz .NET-a07.06.2010. u 15:08 - pre 181 meseci
Hmm, sto vise pratim razvoj situacije ovde, sve vise mi se cini da je greska u dizanju managed contexta.

Ajd malo vise podataka o toj aplikaciji koja poziva DLL, problem definitivno potice odatle? Iz nekog razloga CLR puca kad se podigne unutar njegovog procesa. Da nije neka java aplikacija koja poziva metod preko JNI?
Ako aplikacija uek puca kad se digne managed context, onda nam to namece jedino preostalo resenje.

Caller -> native CPP COM Client ----> COM object -> CCW (Interop) -> .net classw, ti pises bold stvari (ostalo resava .net/windows)

Za COM Interop imas informacije ovde (http://msdn.microsoft.com/en-us/library/6bw51z5z.aspx). U principu napravis managed DLL i exportujes klasu/interrfejs kao COM objekat, onda type library tog COM objekta koristis u pure unmanaged C++ aplikaciji. Sa tim sto pazi, ako ti ovo pukne sa in-process COM objektom, moraces da napravis out-of-process COM. sucks.



Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog
naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji
je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan,
sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv - Z.Đinđić
 
Odgovor na temu

vujkev
Beograd

Član broj: 8072
Poruke: 1347
*.telekom.rs.



+104 Profil

icon Re: Export funkcije iz .NET-a07.06.2010. u 16:38 - pre 181 meseci
Aplikacija je klasična Win, ako se dobro sećam nekog razgovora od pre par godina pisana je u Delphi-u.
Greška koju dobijam je
Citat:

99-0-1-04-0002:
A fatal error has occured. The application will terminate. Please contact PrintSoft Technical Support with the following exception information: Exception code=e0434352, Address = 7C812AFB.


Probaću da napišem ovo isto koristeći COM, a ako ne uspem znam kome da se obratim :)
Naučio sam...
Da je važnije biti ljubazan nego biti u pravu
 
Odgovor na temu

vujkev
Beograd

Član broj: 8072
Poruke: 1347
*.telekom.rs.



+104 Profil

icon Re: Export funkcije iz .NET-a07.06.2010. u 18:29 - pre 181 meseci
USPEO SAM, ali opet delimično :)

ovo je kod za .NET projekat. Ništa posebno, ali je uključena COM podrška
Code (vbnet):

Imports System.Runtime.InteropServices

<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)> _
Public Interface test
    <DispId(1)> _
    Sub Test(ByVal str1 As String, ByVal str2 As String)
End Interface

<ClassInterface(ClassInterfaceType.None)> _
Public Class Class1
    Implements test
    Public Sub test(ByVal str1 As String, ByVal str2 As String) Implements netlib.test.Test
        MsgBox(String.Format("str1:{0} - str2:{1}", str1, str2))
    End Sub
    Sub New()
    End Sub
End Class
 


CPP kod u običnom Win32 projektu
Code (cpp):

#include "stdafx.h"
#include "windows.h"
#import "../debug/netlib.tlb"   //tlb koji dobijem prilikom kreiranja .NET assembly-a
using namespace netlib;

extern "C" __declspec(dllexport)  bool  __stdcall UserInstruction(HWND hWnd,HINSTANCE hInst,double *nArray,LPSTR lpData1,LPSTR lpData2)
{    
    netlib::test *com_ptr;
    CoInitialize(NULL);
    netlib::testPtr p(__uuidof(Class1));
   
    p->_test( lpData1, lpData2 );
    return (true);
}
 


stringovi prolaze bez problema, ali dobijam grešku
Citat:

cannot convert parameter from 'double' to 'SAFEARRAY *'

ukoliko pokušam da pošaljem nArray. Na net-u ne nalazim kako da napravim ovu konverziju.

inače, gore napisani kod sam našao na netu i malo modifikovao :)

[Ovu poruku je menjao vujkev dana 07.06.2010. u 19:50 GMT+1]

[Ovu poruku je menjao mmix dana 07.06.2010. u 21:05 GMT+1]
Naučio sam...
Da je važnije biti ljubazan nego biti u pravu
 
Odgovor na temu

deerbeer
Beograd

Član broj: 174418
Poruke: 1189
*.mbb.telenor.rs.



+395 Profil

icon Re: Export funkcije iz .NET-a07.06.2010. u 18:49 - pre 181 meseci
Za LPSTR tip koristi StringBuilder ,
a za double* pokusaj sa MarshalAsAttribute (UnmanagedType.LPArray )
pa da double pointer bude prosledjen kao niz .


Viva lollapalooza
 
Odgovor na temu

vujkev
Beograd

Član broj: 8072
Poruke: 1347
*.telekom.rs.



+104 Profil

icon Re: Export funkcije iz .NET-a07.06.2010. u 19:33 - pre 181 meseci
Stringovi prolaze bez ikakve konverzije - samao prosledim parametar

MarshalAsAttribute (UnmanagedType.LPArray ) - zar ovo nije komanda iz managed koda? meni treba da se array iz native koda da se prebaci u managed kod
Naučio sam...
Da je važnije biti ljubazan nego biti u pravu
 
Odgovor na temu

mmix
Miljan Mitrović
Chief Software Architect
Financial Intelligence Software Ltd.
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6050



+4631 Profil

icon Re: Export funkcije iz .NET-a07.06.2010. u 20:54 - pre 181 meseci
Nema ovde marshalovanja, ovo je unmanaged code. Ovo je konverzija iz native C++ parametara u COM-compatible parametre.

Znaci, treba ti kod da pretvori double* u safearray. Implicitna konverzija nije moguca, moras da uradis sledece:

1. ODredis koliko elemenata ima u nArray (pretpostavljam da je null terminated niz, pa ces morati da prebrojis "rucno")
2. Kreiras SAFEARRAY sa alociranim bufferom za podatke
3. Kopiras podatke iz tvog niza u buffer safearray-a


otprilike:

Code (cpp):

     // prebroj niz
     int i = 0; while(nArray[i]) i++;

     // kreiraj safe array sa alociranim blobom, VT_R8 je double (real sa 8 bajtova)
     SAFEARRAY* snArray = SafeArrayCreateVector(VT_R8, 0, i);

     // kopiraj niz u array buffer (prvo ga lockuj)
     void *pData;
     HRESULT hr = SafeArrayAccessData(snArray, (void **)&pData);
     memcpy(pData, nArray, i*8);
     SafeArrayUnaccessData(snArray);

     // u poziv saljes SAFEARRAY*
     p->_test( lpData1, lpData2, snArray );

     // OBAVEZNO: ti si kreirao safe array, kad ti vise ne treba ti moras da ga unistis inace mem leak.
     SafeArrayDestroy(snArray);
 

Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog
naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji
je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan,
sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv - Z.Đinđić
 
Odgovor na temu

mmix
Miljan Mitrović
Chief Software Architect
Financial Intelligence Software Ltd.
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6050



+4631 Profil

icon Re: Export funkcije iz .NET-a07.06.2010. u 21:09 - pre 181 meseci
Btw, kod e0434352 je genericki kod za exception u CLRu, sto znaci da ti je managed context podignut ali da je managed metod bacio exception koji je unhandled unutar managed contexta i pobegao napolje (a posto je native kod nesvestan CLR exceptiona puca kao ovaj LastErrorCode). Ako hoces mozemo da uradimo par debug trikova da vidimo sta je izazvalo exception (pretpostalvjam da je neki los marshaling u pitanju). Mislim da ti je to mozda bolje nego da za svaki plugin pises poseban COM i poseban interop (plus sto je sporije).
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog
naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji
je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan,
sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv - Z.Đinđić
 
Odgovor na temu

vujkev
Beograd

Član broj: 8072
Poruke: 1347
*.telekom.rs.



+104 Profil

icon Re: Export funkcije iz .NET-a10.06.2010. u 07:26 - pre 181 meseci
Sastavio sam kompletan kod i radi.
HVALA svima, ali imam još jedno pitanje :(
Ukoliko promenim vrednost nekog elementa nArray-a (nArray[1] = 54), ta vrednost se vraća pozivaocu. Da li to isto mogu da uradim sa stringovima i kako pošto lpData1 = "test" ne radi.

Što se tiče eksperimentisanja sa C++/CLI naravno da sam raspoložen. Reci samo šta da uradim i probaću


Naučio sam...
Da je važnije biti ljubazan nego biti u pravu
 
Odgovor na temu

mmix
Miljan Mitrović
Chief Software Architect
Financial Intelligence Software Ltd.
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6050



+4631 Profil

icon Re: Export funkcije iz .NET-a10.06.2010. u 10:15 - pre 181 meseci
Tesko ces to. Morao bi da ga menjas na isti nacin na koji menjas nArray, tako sto menjas postojece memorijske lokacije koje zauzima string pozivaca. LPSTR je u osnovi char*, pointer na niz karaktera terminisan nulom. Tako da mozda bi mogao da ubacis "Perica\0" umesto "Slavomir\0" jer je krace, ali ne bi smeo da stavis "Slavomir\0" umesto "Perica\0" jer ces verovatno pregaziti neki drugi buffer, mozda cak i izazvati segfault. Kad se stringovi vracaju pozivacu u c/C++u to se radi preko char** i slicnih tako da je vrlo verovatno da ni pozivao nece registrovati da si mu promenio string jer to ne ocekuje.


Ajd sad da probamo sledece.

1. Napravi solution gde imas c++/CLI wrapper i drugi managed projekat koji se poziva iz c++-a, kao onaj projekat u kojem dobijas fatal error. Sve izbilduj u debug modu.
2. Prebaci VS debager da hvata exceptione pre procesiranja. TO radis tako sto u Debug meniju izaberes "Exceptions" i "Common Language Runtime Exceptions" prebacis na Thrown. (posle ti to vrati na off da te ne smara za druge projekte). Ovo znaci da ce VS da breakuje program na prvoj debugable liniji u kojoj nastane exception, u nasem slucaju pre nego sto ga manage/unmanaged thunk pretvori u fatal error.
3a. Treba da pokrenes userhook u debug modu, a kako to uraditi zavisi od toga sta je userhook? Ako je exe koji pozivas iz komandne linije onda ga stavi u debug folder C++ projekta gde je c++ DLL (tu prebaci managed dll i pdb, nek ti pdb uvek ide u pratnji). Nek ti C++ projekat bude startup projekat. Udji u properties od C++ projekta i lociraj Configuration Properties/Debugger. Promeni Command iz $(TargetPath) u $(TargetDir)\userhook.exe a u command arguments stavi ono sto bi stavio iza userhook komande. Debugger Type prebaci u "Managed Only" ili "Mixed". Pokreni projekat u debug modu (F5). VS ce pozvati userhook i zakaciti se za njega, on ce ucatati c++ dll koji ce ucitati maanged DLL koji ce puknuti.

Ako je to komanda koju ukucavas u konzolu neke aplikacije (te delphi) onda 3b:
3b. (ako nije komandna linija) Iz debug menija izaberi Attach to process i lociraj aplikaciju. Promeni attach to: sa "automatic" na "Managed" (i eventualno native ako hoces da single-stepujes kroz C++ deo). Attach. i posle iz aplikacije pokreni user hook da izazoves gresku

Ako je sve ok trebalo bi da ti breakuje u VSu kad nastupi managed exception.

Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog
naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji
je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan,
sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv - Z.Đinđić
 
Odgovor na temu

vujkev
Beograd

Član broj: 8072
Poruke: 1347
212.200.241.*



+104 Profil

icon Re: Export funkcije iz .NET-a11.06.2010. u 19:25 - pre 181 meseci
Samo Managed attach ne stopira izvršenje koda već sam morao da uključim i native attach. Evo spiska grešaka
Citat:

First-chance exception at 0x7c812afb in prsAFPDP.exe: Microsoft C++ exception: EEFileLoadException at memory location 0x0012d46c..
First-chance exception at 0x7c812afb in prsAFPDP.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000..
First-chance exception at 0x7c812afb in prsAFPDP.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000..
First-chance exception at 0x7c812afb in prsAFPDP.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000..
First-chance exception at 0x7c812afb in prsAFPDP.exe: Microsoft C++ exception: MalformedURLException at memory location 0x0012b7b4..
First-chance exception at 0x7c812afb in prsAFPDP.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000..
First-chance exception at 0x7c812afb in prsAFPDP.exe: Microsoft C++ exception: MalformedURLException at memory location 0x0012b5a0..
First-chance exception at 0x7c812afb in prsAFPDP.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000..
First-chance exception at 0x7c812afb in prsAFPDP.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000..
First-chance exception at 0x7c812afb in prsAFPDP.exe: Microsoft C++ exception: EndOfEntityException at memory location 0x0012b648..


prsafpdp.exe je aplikacija koja poziva userinstruction funkciju (nije komandna linija)
Naučio sam...
Da je važnije biti ljubazan nego biti u pravu
 
Odgovor na temu

mmix
Miljan Mitrović
Chief Software Architect
Financial Intelligence Software Ltd.
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6050



+4631 Profil

icon Re: Export funkcije iz .NET-a11.06.2010. u 20:08 - pre 181 meseci
Hmm, kako izgleda struktura foldera. gde je prsafpdp.exe a gde su c++ i managed DLL?

Ako nisu u istom folderu probaj da managed dll prebacis tamo gde je EXE. Postoji fora sa lociranjem managed DLLa, CLR ga nece potraziti tamo gde je unmanaged DLL vec tamo gde je glavni EXE fajl (plus u GACu)
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog
naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji
je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan,
sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv - Z.Đinđić
 
Odgovor na temu

vujkev
Beograd

Član broj: 8072
Poruke: 1347
212.200.241.*



+104 Profil

icon Re: Export funkcije iz .NET-a13.06.2010. u 00:10 - pre 181 meseci

fajlovi su bili na odvojenoj lokaciji, prebacio ih tamo gde je exe - ne radi; prebacio u system32 - ne radi; dodao .NET managed assembly u GAC i sad radi :)

kako sad da konvertujem double *nArray u array<double>^ d?? Ako je bitno možemo da kažemo da će array uvek imati 10 elemenata
Naučio sam...
Da je važnije biti ljubazan nego biti u pravu
 
Odgovor na temu

vujkev
Beograd

Član broj: 8072
Poruke: 1347
*.telekom.rs.



+104 Profil

icon Re: Export funkcije iz .NET-a13.06.2010. u 08:21 - pre 181 meseci
uspeo :)
Code (cpp):

extern "C" __declspec(dllexport)  bool  __stdcall UserInstruction(HWND hWnd,HINSTANCE hInst,double *nArray,LPSTR lpData1,LPSTR lpData2) {
     IntPtr hwnd(hWnd);
    IntPtr hinst(hInst);
     IntPtr arr(nArray);
     array<double>^ d = gcnew array<double>(5);
     Marshal::Copy(arr, d, 0, 5);
    String^ data1 = Marshal::PtrToStringAnsi(IntPtr(lpData1));
    String^ data2 = Marshal::PtrToStringAnsi(IntPtr(lpData2));

     NetTest::Class1 ^ t = gcnew NetTest::Class1();
     t->Test(hwnd, hinst, d, data1, data2);

     return (true);
}


sad mi ostaje samo da string parametri koje caller šalje budu ByRef tj. da se promene na stringovima u ovoj funkciji vide i u programu koji je poziva. Stringovi se šalju ovoj proceduri tako što se u pozivaocu prvo definiše buffer od npr 2000 karaktera i onda se u njega ubaci tekst terminisan nulom. Prema tome slobodno mogu da menjam string to veličine tog buffera, pitanje je samo kako. Da li u ovoj proceduri mogu da znam kolika je veličina buffera?
Naučio sam...
Da je važnije biti ljubazan nego biti u pravu
 
Odgovor na temu

mmix
Miljan Mitrović
Chief Software Architect
Financial Intelligence Software Ltd.
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6050



+4631 Profil

icon Re: Export funkcije iz .NET-a13.06.2010. u 14:27 - pre 181 meseci
Prilicno prosto, postoji metod u marshal koji konvertuje CLR string u ansi char* string, samo ga treba posle iskopirati u tvoj buffer i osloboditi marshalovani string (managed delovi ce se sami ocistiti kroz GC). Evo primer (narano bez iakavih buffer overrun provera, koristi na svoju odgovornost

Code (vbnet):


Public Class Class1
    Public Sub Test(ByVal hWnd As IntPtr, ByVal hInst As IntPtr, ByVal nArray As Double(), ByRef lpData1 As String, ByRef lpData2 As String)
        MsgBox(lpData1 + "" + lpData2)
        lpData1 = "Milisav"
        lpData2 = "Zivorad"
        nArray(1) = 123
    End Sub

End Class


Code (cpp):

#include "stdafx.h"
#include "windows.h"

using namespace System;
using namespace System::Runtime::InteropServices;

extern "C" __declspec(dllexport)  bool  __stdcall UserInstruction(HWND hWnd,HINSTANCE hInst, double *nArray,LPSTR lpData1,LPSTR lpData2)
{    
     array<double>^ d = gcnew array<double>(5);
     Marshal::Copy(IntPtr(nArray), d, 0, 5);
     String^ data1 = Marshal::PtrToStringAnsi(IntPtr(lpData1));
     String^ data2 = Marshal::PtrToStringAnsi(IntPtr(lpData2));

     NetTest::Class1 ^ t = gcnew NetTest::Class1();
     t->Test(IntPtr(hWnd), IntPtr(hInst), d, data1, data2);

     // kopiraj rezultat, ovaj deo tebi treba
     Marshal::Copy(d, 0, IntPtr(nArray), 5);
     IntPtr d1 = Marshal::StringToHGlobalAnsi(data1);
     strcpy(lpData1, d1.ToPointer());
     IntPtr d2 = Marshal::StringToHGlobalAnsi(data2);
     strcpy(lpData2, d2.ToPointer());
     Marshal::FreeHGlobal(d1);
     Marshal::FreeHGlobal(d2);

     return (true);
}


int main(array<System::String ^> ^args)
{
     // imitiramo unmanaged pozivaoca
     char buff1[2000], buff2[2000];
     strcpy(buff1, "Pera");
     strcpy(buff2, "Mika");
     double nArr[] = {1,2,3,4,5};

     UserInstruction(NULL, NULL, nArr, buff1, buff2);

     Console::WriteLine(Marshal::PtrToStringAnsi(IntPtr(buff1)));
     Console::WriteLine(Marshal::PtrToStringAnsi(IntPtr(buff2)));
     for(int i=0; i<5; i++) Console::WriteLine(nArr[i]);
     Console::ReadLine();

     return 0;
}


Rezultat:
Milisav
Zivorad
1
123
3
4
5


EDIT: strcpy je primereniji za kopiranje char* stringova, isti trip samo dinamicki otkriva duzinu

[Ovu poruku je menjao mmix dana 13.06.2010. u 15:39 GMT+1]
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog
naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji
je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan,
sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv - Z.Đinđić
 
Odgovor na temu

mmix
Miljan Mitrović
Chief Software Architect
Financial Intelligence Software Ltd.
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6050



+4631 Profil

icon Re: Export funkcije iz .NET-a13.06.2010. u 15:54 - pre 181 meseci
I da, neodgovoreno pitanje, ne mozes dinamicki da otkrijes velicinu buffera pozivaoca, ili dokumentacija ili da kontaktiras autore. Zato npr COM ne dozvoljava type* konstrukcije vec radi samo sa SAFEARRAY koji u sebi vuce sve podatke neophodne za opis niza, slicna prica je i za System::Array u CLRu. Iz istih razloga kad pozivas unmanaged API iz C++a uvek ide i dodatni parametar kojim pozvanoj API funkciji kazujes koliki buffer si joj prosledio u type*.
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog
naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji
je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan,
sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv - Z.Đinđić
 
Odgovor na temu

vujkev
Beograd

Član broj: 8072
Poruke: 1347
212.200.241.*



+104 Profil

icon Re: Export funkcije iz .NET-a13.06.2010. u 16:05 - pre 181 meseci
Hvala, takav kod sam manje više i ja sastavio koristeće odgovore sa codeguru foruma. Pošto mogu da kontrolišem sve parametre koji se šalju ovoj funkciji staviću uslov da u array-u koji prosleđujem prva dva parametra moraju da budu veličine buffera i problem rešen. Ako neko baš hoće da laže ... pa njihov problem pošto ovo neće raditi :)

HVALA još jednom
Naučio sam...
Da je važnije biti ljubazan nego biti u pravu
 
Odgovor na temu

[es] :: .NET :: Export funkcije iz .NET-a

Strane: 1 2

[ Pregleda: 4106 | Odgovora: 35 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.