Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

P/Invoke

8 réponses
Avatar
J
Bonjour,

Je dois faire une dll (pas un objet com) réalisant une opération qui
retourne un tableau binaire.

J'ai bien vu qu'il serait possible de transmettre un pointeur sur un
tableau Fixed à la fonction non managée. Mais le problème est que je ne
connais pas par avance la taille du tableau.

Je pense utiliser les api GlobalAlloc / GlobalLock /GlobalFree pour que
ma fonction retourne un handle sur un bloc mémoire allouée par la dll.

Il y a de meilleures solutions ?

Merci.

Jean

8 réponses

Avatar
Gilles TOURREAU
Le Mon, 18 Jun 2007 16:16:33 +0200, J a écrit:

Bonjour,

Je dois faire une dll (pas un objet com) réalisant une opération qui
retourne un tableau binaire.

J'ai bien vu qu'il serait possible de transmettre un pointeur sur un
tableau Fixed à la fonction non managée. Mais le problème est que je ne
connais pas par avance la taille du tableau.

Je pense utiliser les api GlobalAlloc / GlobalLock /GlobalFree pour que
ma fonction retourne un handle sur un bloc mémoire allouée par la dll.

Il y a de meilleures solutions ?

Merci.

Jean



Dans tout code non-managée il faut toujours envoyer le pointeur de votre
zone mémoire (tableau) + la taille de celle-ci...

Cordialement

--
Gilles TOURREAU


S.A.R.L. P.O.S
Le spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr
Avatar
J
Gilles TOURREAU a écrit :

Dans tout code non-managée il faut toujours envoyer le pointeur de votre
zone mémoire (tableau) + la taille de celle-ci...



Je ne comprends pas bien.
En c#, au moment de l'appel de la fonction non-managée, je ne connais
pas la taille de la zone mémoire.
Je pourrais faire une autre fonction retournant la taille nécessaire
mais ça serait inefficace (car l'opération complexe qui génère les
données de ce tableau est très coûteuse).

Il *faut* donc que la fonction non-managée retourne d'une manière ou
d'une autre un tableau, un bloc mémoire, alloué par elle. Et là seule
solution que je vois pour l'instant est d'utiliser GlobalAlloc etc.
Ou un fichier temporaire éventuellement.

Jean
Avatar
Gilles TOURREAU
Le Mon, 18 Jun 2007 17:04:34 +0200, J a écrit:

Gilles TOURREAU a écrit :

Dans tout code non-managée il faut toujours envoyer le pointeur de
votre zone mémoire (tableau) + la taille de celle-ci...



Je ne comprends pas bien.
En c#, au moment de l'appel de la fonction non-managée, je ne connais
pas la taille de la zone mémoire.
Je pourrais faire une autre fonction retournant la taille nécessaire
mais ça serait inefficace (car l'opération complexe qui génère les
données de ce tableau est très coûteuse).

Il *faut* donc que la fonction non-managée retourne d'une manière ou
d'une autre un tableau, un bloc mémoire, alloué par elle. Et là seule
solution que je vois pour l'instant est d'utiliser GlobalAlloc etc.
Ou un fichier temporaire éventuellement.

Jean



Normalement votre fonction managée devrait être comme ceci :

BOOL fonction(void** buffer, int* longueur taille);

L'appel de dans .NET ce fait donc :

[Avec les attributs qui vont bien ! :-)]
extern static boolean fonction(out IntPtr, out int taille)

void Toto()
{
IntPtr p;
int taille;
if (fonction(out p, out taille) == true)
{
//Faire une boucle qui lit à l'aide de Marshal.Readxxxx() en
s'aidant de taille et de p
}

}


Pouvez-vous détailler le type de tableau que vous retournez (copier coller
votre prototype non-managé) ?

Cordialement

--
Gilles TOURREAU


S.A.R.L. P.O.S
Le spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr
Avatar
J
Gilles TOURREAU a écrit :

Normalement votre fonction managée devrait être comme ceci :



"fonction *non* managée" je suppose ?

BOOL fonction(void** buffer, int* longueur taille);



En gros oui (c'est du delphi mais peu importe).

L'appel de dans .NET ce fait donc :

[Avec les attributs qui vont bien ! :-)]
extern static boolean fonction(out IntPtr, out int taille)



Ok.

void Toto()
{
IntPtr p;
int taille;
if (fonction(out p, out taille) == true)
{
//Faire une boucle qui lit à l'aide de Marshal.Readxxxx() en
s'aidant de taille et de p
}

}


Pouvez-vous détailler le type de tableau que vous retournez (copier
coller votre prototype non-managé) ?



Le tableau que la fonction non-managée doit créer est un simple tableau
d'octets (de taille variable, mais pouvant être importante). Le
prototype que vous avez choisi (pour "fonction") est suffisant.

Ce qui m'intrigue, c'est par quelle méthode le tableau est alloué (dans
la fonction non-managée). Enfin, alloué n'est pas vraiment le problème,
c'est surtout la libération qui m'intrigue. Ou alors, je dois prévoir
une fonction dans la dll qui va libérer la mémoire.

Jean
Avatar
Gilles TOURREAU
Le Mon, 18 Jun 2007 19:07:16 +0200, J a écrit:

Gilles TOURREAU a écrit :

Normalement votre fonction managée devrait être comme ceci :



"fonction *non* managée" je suppose ?

BOOL fonction(void** buffer, int* longueur taille);



En gros oui (c'est du delphi mais peu importe).

L'appel de dans .NET ce fait donc :
[Avec les attributs qui vont bien ! :-)]
extern static boolean fonction(out IntPtr, out int taille)



Ok.

void Toto()
{
IntPtr p;
int taille;
if (fonction(out p, out taille) == true)
{
//Faire une boucle qui lit à l'aide de Marshal.Readxxxx() en
s'aidant de taille et de p
}
}
Pouvez-vous détailler le type de tableau que vous retournez (copier
coller votre prototype non-managé) ?



Le tableau que la fonction non-managée doit créer est un simple tableau
d'octets (de taille variable, mais pouvant être importante). Le
prototype que vous avez choisi (pour "fonction") est suffisant.

Ce qui m'intrigue, c'est par quelle méthode le tableau est alloué (dans
la fonction non-managée). Enfin, alloué n'est pas vraiment le problème,
c'est surtout la libération qui m'intrigue. Ou alors, je dois prévoir
une fonction dans la dll qui va libérer la mémoire.

Jean



Il est alloué comment exactement ? Pouvez-vous poster le bout de code qui
s'occupe de faire cela ?

Cordialement

--
Gilles TOURREAU


S.A.R.L. P.O.S
Le spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr
Avatar
J
Gilles TOURREAU a écrit :

Il est alloué comment exactement ? Pouvez-vous poster le bout de code
qui s'occupe de faire cela ?



Pour l'instant, je n'ai rien, je cherche une solution.

Mais je n'ai pas dû correctement décrire le problème : je dois créer une
fonction en delphi (win32) dans une dll. Cette dll devra être appelée
depuis un webservice c#. Cette fonction fait une opération "compliquée"
et doit retourner au webservice un tableau (un bloc de données sans
structure particulière).

Donc, justement, je m'interroge sur la méthode à employer dans ma
fonction delphi pour allouer le bloc mémoire qui devra être transmis au
webservice.

Jean
Avatar
Gilles TOURREAU
Le Mon, 18 Jun 2007 21:48:44 +0200, J a écrit:

Gilles TOURREAU a écrit :

Il est alloué comment exactement ? Pouvez-vous poster le bout de code
qui s'occupe de faire cela ?



Pour l'instant, je n'ai rien, je cherche une solution.

Mais je n'ai pas dû correctement décrire le problème : je dois créer une
fonction en delphi (win32) dans une dll. Cette dll devra être appelée
depuis un webservice c#. Cette fonction fait une opération "compliquée"
et doit retourner au webservice un tableau (un bloc de données sans
structure particulière).

Donc, justement, je m'interroge sur la méthode à employer dans ma
fonction delphi pour allouer le bloc mémoire qui devra être transmis au
webservice.

Jean



Dans ce cas, il faut que tu alloue un bloc via la fonction GlobalAlloc()
de Windows (sera visible par tous les programmes).
Je te conseille de créer une fonction pour que ta DLL delphi puisse
libérer la mémoire (GlobalFree()).

Ton webservice devra alors appeler la fonction pour récupérer le tableau
et après l'avoir récupérer appeler la méthode permettant de libérer la
mémoire...

Cordialement

--
Gilles TOURREAU


S.A.R.L. P.O.S
Le spécialiste en motoculture depuis + de 30 ans !
http://www.pos.fr
Avatar
J
Gilles TOURREAU a écrit :

Dans ce cas, il faut que tu alloue un bloc via la fonction GlobalAlloc()
de Windows (sera visible par tous les programmes).
Je te conseille de créer une fonction pour que ta DLL delphi puisse
libérer la mémoire (GlobalFree()).

Ton webservice devra alors appeler la fonction pour récupérer le tableau
et après l'avoir récupérer appeler la méthode permettant de libérer la
mémoire...



Merci pour ton aide. C'est à peu près ce que j'avais imaginé comme solution.

Jean