Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

CHARGER UNE POLICE DEPUIS UN FICHIER OU UNE RESSOURCE (WIN32)


Information sur la source

Catégorie :Astuces Classé sous : addfontmemresourceex, police, font, ressource, createfont Niveau : Débutant Date de création : 02/08/2006 Date de mise à jour : 12/08/2006 12:23:43 Vu / téléchargé: 7 146 / 426

Note :
Aucune note

Commentaire sur cette source (63)
Ajouter un commentaire et/ou une note


Description

Cliquez pour voir la capture en taille normale
Ce code montre comment utiliser la fonction AddFontMemResourceEx dans le but de créer une police a partir d'un fichier qui n'est pas dans le dossier des polices de Windows, ou bien depuis une ressource de l'exécutable.
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Historique

12 août 2006 12:23:43 :
Appel de FreeResource Appel de RemoveFontMemResourceEx directement après CreateFont Remplacement memset par fonction perso

Commentaires et avis

signaler à un administrateur
Commentaire de MuPuF le 03/08/2006 01:25:27

oh super !, merci, ça va vraiment me servir, je fais actuelle une classe pour gerer les skins, ta source va apporter un réel plus !

La source compile sans probleme et fonctionne parfaitement.

Encore une fois merci ;-)

signaler à un administrateur
Commentaire de vecchio56 le 03/08/2006 01:27:33 administrateur CS

Je savais que t'en avais besoin sinon je l'aurais jamais faite ;)

signaler à un administrateur
Commentaire de MuPuF le 03/08/2006 01:30:11

hey hey vecchiodamus ;-)

signaler à un administrateur
Commentaire de MorbhAck le 03/08/2006 03:00:22

Sa marche a merveille ! MERCI encore une fois ( a putin ce que chui leche cul ! ) :)

signaler à un administrateur
Commentaire de mogwai93 le 03/08/2006 08:29:37

Question par rapport à DevCpp :
ca compile mais en remplacant :

#ifdef _DEBUG
int main()
#else
#pragma comment(linker, "/entry:myWinMain")
int __stdcall myWinMain()
#endif

par :
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
   LPSTR lpCmdLine, int nCmdShow)

et
#ifdef _DEBUG
  return (int)msg.wParam;
#else
  ExitProcess(msg.wParam);
#endif

par :
     return msg.wParam;


sinon, j'ai une erreur :
  [Linker error] undefined reference to `WinMain@16'
  ld returned 1 exit status

quelqu'un peut m'expliquer ?
merci

signaler à un administrateur
Commentaire de vecchio56 le 03/08/2006 10:35:19 administrateur CS

Parce que le #pragma n'est pas compris par gcc

signaler à un administrateur
Commentaire de deck_bsd le 04/08/2006 17:02:51

sir vecchio est en grande forme ces temps si :D Bonne source :D (vivi je peut utiliser les ressources now mdr).

signaler à un administrateur
Commentaire de racpp le 11/08/2006 22:25:23 administrateur CS

Salut,
Merci vecchio56 pour ce code. Je viens de me servir de la fonction AddFontMemResourceEx() dans mon dernier code source déposé il y'a un instant. Cette fonction m'a servi à ajouter une police au système à partir d'une ressource en mémoire. Je viens de remarquer qu'une fois la police ajoutée, la ressource peut être libérée sans problème. Donc un appel de FreeResource() juste après AddFontMemResourceEx() serait préférable.
A propos du #pragma comment(linker, "/entry:myWinMain"), je ne crois pas qu'il soit d'une grande utilité dans ton code. Car même si le point d'entrée du programme évite l'utilisation de la CRT, cette dernière sera de toute façon utilisée dans ton programme. memset() par exemple. Et la taille de l'exe ne sera pas réduite.
Y'a-t-il une autre raison de l'utilisation de cette option du linker?
Merci.

signaler à un administrateur
Commentaire de vecchio56 le 11/08/2006 22:34:45 administrateur CS

Oui pour le  RemoveFontMemResourceEx j'ai vu qu'on peut l'appeler aussitot, le HFONT n'en a pas besoin.
Pour l'option: si, elle diminue la taille de l'exécutable ici (103Ko au lieu de 134Ko avec WinMain)

signaler à un administrateur
Commentaire de racpp le 11/08/2006 23:03:58 administrateur CS

Je pense que non vecchio56, RemoveFontMemResourceEx() ne doit pas être appelée aussitôt. Je viens de tester. La police ne sera plus disponible et sera remplacée par la police par défaut. Moi je parlais de FreeResource():
- Charger la ressource avec LoadResource().
- Appeler AddFontMemResourceEx()
- Libérer la ressouce avec FreeResource().
- Créer la police.
D'après mes tests, RemoveFontMemResourceEx() ne doit être appelée que si on n'aura plus besoin de notre police. Elle fera donc suite à DeleteObject(hPolice)
Puisque tu cherchais à diminuer la taille de l'exe, pourquoi ne pas virer memset()?
WNDCLASSEX wcex={0}; serait suffisant.
Il est à noter que l'API RegisterClassEx() fait implicitement appel à memset() et fait donc augmenter la taille de l'exe. RegisterClass() quant à elle ne fait pas d'appel à la CRT. J'ai découvert tout ça dernièrement. Tu peux faire des tests pour en avoir le coeur net.

signaler à un administrateur
Commentaire de BruNews le 11/08/2006 23:15:20 administrateur CS

C'est fou cette histoire, l'autre jour je me suis retrouvé avec un exe lié à msvcrt8.dll pour cause que l'exe appelait _memset et _memcpy sur cette dll. J'ai viré la dépendance en fournissant mes funcs au lieu des 2 originalez.
Faut dire que c'était la 1ere fois que je notais cela et l'exe de vecchio non plus n'a pas de dépendance.
Je note pourtant le
call _memset
dans l'asm produit par le compilo.
Mystique tout cela, sera à approfondir.

signaler à un administrateur
Commentaire de vecchio56 le 11/08/2006 23:16:03 administrateur CS

OK pour le FreeResource, je regarderai cela
WNDCLASSEX wcex={0}; va sans doute générer un fichier plus gros, il signifie en fait WNDCLASSEX wcex={0, 0, 0, ..., 0}; (cela dit ta solution diminue la taille du fichier source)
RegisterClassEx est une fonction, donc son appel est traduit par un call, rien de plus
Heureusement d'ailleurs, pourquoi ferait-elle un memset? Elle pourrait plus lire les infos dans la structure

signaler à un administrateur
Commentaire de vecchio56 le 11/08/2006 23:17:30 administrateur CS

BruNews> Il en faudra des années avant de comprendre toutes ces options de VS2005. Tout était bien plus simple sous 2003, pas de mauvaises surprises

signaler à un administrateur
Commentaire de BruNews le 11/08/2006 23:21:57 administrateur CS

Mais le + fort, je viens de comparer les options linker et compilo de ton proj avec le mien, exactement les mêmes.
S'il y a de l'alea dans le binaire maintenant, tout est perdu...

signaler à un administrateur
Commentaire de racpp le 11/08/2006 23:49:50 administrateur CS

vecchio56 >> Avec WNDCLASSEX wcex={0} la taille de l'exe est plus petite car memset() ajoute beaucoup plus d'octets. J'avais déja fait des tests. Je parle bien sûr d'un exe autonome sans aucune dépendance.
brunews >> C'est justement à cause de cette msvcrt80.dll que j'ai découvert tout cela. Cette dll n'est pas présente sur tous les ordinateurs et cela nous oblige à la lier statiquement dans le programme. Même en virant toute référence à la CRT, mes programmes en dépendent toujours à cause de certaines APIs. RegisterClassEx() n'est pas la seule car j'ai remarqué le même comportement avec d'autres. J'ai l'intention de les répertorier et essayer de faire un tutorial à ce sujet.

signaler à un administrateur
Commentaire de racpp le 12/08/2006 00:36:51 administrateur CS

Il s'agit de msvcr80.dll et non msvcrt.dll. Désolé pour l'erreur.
vecchio56 >> Je viens de compiler ton projet tel quel sans rien changer. Au linkage j'ai deux warnings du genre:
warning LNK4210: .CRT section exists; there may be unhandled static initializers or terminators

Ca prouve bien qu'il y'a de la dépendance à la CRT. Pourtant, Depends n'affiche aucune dépendance. En remplaçant WNDCLASSEX par WNDCLASS et RegisterClassEx() par RegisterClass() les warnings disparaissent et la taille de l'exe descend à 100ko. Ca veut dire que RegisterClassEx() provoque implicitement l'ajout du code de _memeset à l'exéutable. C'est vrai qu'on se demande pouquoi cette API appellerait _memset().


signaler à un administrateur
Commentaire de racpp le 12/08/2006 00:51:42 administrateur CS

Je viens de remarquer qu'on ne peut pas déscendre sous les 100ko car la ressource seule fait 97ko.

signaler à un administrateur
Commentaire de vecchio56 le 12/08/2006 11:29:46 administrateur CS

En effet plus de warning avec RegisterClassEx (en fait je pensais que le warning était présent dès lors qu'on personnalisait le point d'entrée). Comment sais-tu que c'est memset qui est appelée par RegisterClassEx?
De toutes facons je comprends pas: le code de RegisterClassEx est situé dans user32.dll, et donc même si cette api utilise la CRT, ce devrait être indépendant de notre programme, non?

signaler à un administrateur
Commentaire de vecchio56 le 12/08/2006 11:41:53 administrateur CS

En fait le warning apparait quand on utiliser à la fois memset et RegsiterClassEx

RegisterClassEx -> pas de warning
memset et RegisterClassEx -> warning
memset et RegisterClass -> pas de warning

Je regarderait les sorties asm pour voir

signaler à un administrateur
Commentaire de vecchio56 le 12/08/2006 11:57:50 administrateur CS

Le memset est inlinée pour WNDCLASS et pas pour WNDCLASSEX
Parce que WNDCLASSEX est plus grande et doit donc dépasser la limite pour être inlinée

signaler à un administrateur
Commentaire de vecchio56 le 12/08/2006 12:02:21 administrateur CS

A partir de 44 octets memset n'est plus inlinée en fait

signaler à un administrateur
Commentaire de vecchio56 le 12/08/2006 12:12:44 administrateur CS

racpp, même en écrivant WNDCLASSEX wcex = {0}; le compilo appelle memset
Je crois qu'il faut donc employer la méthode de BruNews: une fonction perso

signaler à un administrateur
Commentaire de racpp le 12/08/2006 16:47:39 administrateur CS

Bonjour,
Chez moi le warning apparait avec RegisterClassEx(), seule ou avec memset().
A propos de RegisterClassEx(), je suis tout à fait d'accord. Si elle appelle _memset(), ça doit être en dehors de notre prog.
Personnellement, quand je veux que mon exe soit le plus petit possibe, je mets le code en C, je mets l'option /NODEFAULTLIB pour le linker et /GS- pour le compilateur. Je fouris dans le code la fonction d'entrée WinMainCRTStartup(). Un jour, en étant sûr que mon code ne fait aucun appel à la CRT, je me retrouve devant des erreurs indiquant les fonctions de la CRT manquantes. J'ai alors mis en commentaire tout le code sauf la WinMain(). Et là je découvre qu'avec RegisterClassEx() le linker demande _memset(). En la remplaçant par RegisterClass(), l'erreur diparait et l'exe est généré.
Dans le post suivant, je mettrai un petit exemple de code à tester.

signaler à un administrateur
Commentaire de vecchio56 le 12/08/2006 16:55:33 administrateur CS

Comme j'ai dit plus haut, c'est seulement du au fait que sizeof(WNDCLASSEX)>sizeof(WNDCLASSEX), et qu'a partir d'une certaine taille, memset n'est plus inlinée (sinon ca ferait du code trop gros)

signaler à un administrateur
Commentaire de racpp le 12/08/2006 17:01:35 administrateur CS

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmd,int show)

{
    WNDCLASSEX wc={0};
    RegisterClassEx(&wc);
    return 0;
}


int WINAPI WinMainCRTStartup(void)
{
    int retour;
    retour = WinMain( GetModuleHandle(0),0,0,1 );  
    return retour;
}

signaler à un administrateur
Commentaire de racpp le 12/08/2006 17:06:43 administrateur CS

Oui, tu as raison. Je viens de le voir. C'est plutôt à cause de ces 4 octets de plus de WNDCLASSEX. RegisterClassEx() n'a rien à voir là dedans. Je préfère comme ça car c'était la 1ère fois que je soupçonais une API.

signaler à un administrateur
Commentaire de racpp le 12/08/2006 17:23:23 administrateur CS

Conclusion:
- Pour les tailles inférieures ou égales à 40 octets -> ={0}
- Pour les autres, fournir une fonction perso.

Tu as testé mon petit code? Tu as vu les fonctions manquantes affichées en clair?

signaler à un administrateur
Commentaire de vecchio56 le 12/08/2006 17:27:11 administrateur CS

Je n'ai aucune erreur avec ton exemple. Il est pour VC++ ou Dev-C++?

signaler à un administrateur
Commentaire de racpp le 12/08/2006 17:31:21 administrateur CS

Dans le cas de WNDCLASSEX on peut juste mettre les autres membres à 0 et virer memset(). Ca permet de gagner 3Ko. Sans la ressource, l'exe ne ferait pas plus de 3ko.
Pourquoi ne pas choisir une police d'une dizaine de Ko?

signaler à un administrateur
Commentaire de vecchio56 le 12/08/2006 17:36:25 administrateur CS

Ben je sais pas, c'est grave qu'elle fasse 100Ko?
Pour ton petit code, j'ai pas compris ce que tu voulais montrer avec

signaler à un administrateur
Commentaire de racpp le 12/08/2006 17:59:36 administrateur CS

Ce code est fait pour Visual C Express 2005. Ca doit être pareil avec la version complète car il utilise le même compilo et linker.
J'ai donné le code pour répondre à ta question sur comment je sais que c'est que c'est _memset qui manque. Avec ce code, le linker affiche:
error LNK2001: unresolved external symbol _memset
Si ça t'interesse, je peux t'envoyer le petit projet complet. Avec cette méthode, on est sûr qu'aucune fonction de la CRT n'est ajouté à notre exe.
A propos des 100ko, puisque tu cherches à diminuer la taille de l'exe en mettant ton point d'entrée, pourquoi ne pas choisir une police plus petite et gagner encore des dizaines de ko?

signaler à un administrateur
Commentaire de vecchio56 le 12/08/2006 18:02:50 administrateur CS

Diminuer la taille de l'exe pour moi c'est surtout enlever tout ce qui est inutile. Ici le fichier police est utile donc pas de problème.
Je veux bien voir ton projet

signaler à un administrateur
Commentaire de racpp le 12/08/2006 18:43:43 administrateur CS

J'ai envoyé le projet.
Certes le fichier police est utile, mais un autre de moindre taille sera aussi utile puisque cette police ne sert qu'à démontrer le fonctionnement d'une fonction. Ce serait préférable de choisir un fichier plus petit. Ainsi on gagnera en taille de l'exécutable et en occupation mémoire. C'est mon point de vue.

signaler à un administrateur
Commentaire de BruNews le 12/08/2006 19:43:52 administrateur CS

mov eax, adresse
mov ecx, 44
memZERO:
mov dword ptr[eax], 0
add eax, 4
sub ecx, 4
jnz short memZERO

Changerait quoi qu'on mette 40 ou plus dans ECX ???
Même pas de problème d'alignement puisque le compilo aura par force placé correctement une struct, donc aucun besoin de code de controle préalable.
Ce code pourrait se mettre fort bien direct inline en place d'un appel de fonction.

Un compilo reste un compilo, rassurant pour le codeur manuel...

signaler à un administrateur
Commentaire de racpp le 12/08/2006 20:07:35 administrateur CS

Brunews >> J'aimerais bien avoir ton avis aussi sur le petit projet que j'ai envoyé à vecchio56. C'est une méthode de contrôle total sur les dépendances. Le compilo ignore totalement la CRT et le linker affiche le nom de toute fonction tentant d'y accéder. Si ça t'intéresse, laisse une adresse émail par MP.

signaler à un administrateur
Commentaire de BruNews le 12/08/2006 20:10:34 administrateur CS

OK je vais regarder (après le resto), vecchio me l'a transmis.

signaler à un administrateur
Commentaire de racpp le 12/08/2006 20:16:04 administrateur CS

Ok merci
Bon appétit

signaler à un administrateur
Commentaire de BruNews le 13/08/2006 00:32:56 administrateur CS

ATTENTION, compiler pour regarder listing ASM mais NE PAS LANCER dans cet état.

void __fastcall bnzeromem(void *pmem, DWORD len)
{
  BYTE *p = (BYTE*) pmem;
  DWORD r = len;
  if(!(len >>= 3)) goto prepm1SET;
mem8SET:
  *((DWORD*) p) = 0;
  *((DWORD*) (p + 4)) = 0;
  p += 8;
  if(len -= 8) goto mem8SET;
prepm1SET:
  if(!(r &= 7)) goto zeromemEXIT;
mem1SET:
  *p++ = 0;
  if(--r) goto mem1SET;
zeromemEXIT: return;
}

#pragma comment(linker, "/entry:myWinMain")
void WINAPI myWinMain(void)
{
  //WNDCLASSEX wc={0};
  WNDCLASSEX wc;
  //memset(&wc, 0, sizeof(WNDCLASSEX));
  //RtlZeroMemory(&wc, sizeof(WNDCLASSEX));
  //bnzeromem(&wc, sizeof(WNDCLASSEX));
  bnzeromem(&wc, GetTickCount());
  RegisterClassEx(&wc);
  ExitProcess(0);
}

Ce que je pense être le mieux si on ne veut pas de CRT et surtout ne pas sacrifier la vitesse (tout de même le + important).
WNDCLASSEX wc={0}; comme vu + haut, provoque un appel memset, exclus puisque non inline.
RtlZeroMemory(&wc, sizeof(WNDCLASSEX)); compilo remplace par memset, idem exclus.

bnzeromem(&wc, sizeof(WNDCLASSEX)); incroyable, le compilo a mis 2 affectations de 4 octets et fini, mystère complet. Espérons que ne se produira pas dans un vrai prog complet, à vérifier.
Voila tout ce qu'il en reste, histoire de fou:
@bnzeromem@8 PROC
; _pmem$ = eax
$mem8SET$77844:
   mov  DWORD PTR [eax], 0
   mov  DWORD PTR [eax+4], 0
$prepm1SET$77843:
$zeromemEXIT$77849:
   ret  0
@bnzeromem@8 ENDP

En forçant une valeur "aléatoire" (GetTickCount), alors là NICKEL !!!
Passage correct en registres, tout se fait dans les 3 registres généraux donc pas de 'push pop', pas 1 cycle de perdu, parfait.
@bnzeromem@8 PROC
; _pmem$ = eax
; _len$ = ecx
; 20 :   BYTE *p = (BYTE*) pmem;
; 21   :   DWORD r = len;
    mov edx, ecx
; 22   :   if(!(len >>= 3)) goto prepm1SET;
   shr   ecx, 3
   je   SHORT $prepm1SET$77843
   npad   9
$mem8SET$77844:
   mov   DWORD PTR [eax], 0
   mov   DWORD PTR [eax+4], 0
   add   eax, 8
   sub   ecx, 8
   jne   SHORT $mem8SET$77844
$prepm1SET$77843:
; 29   :   if(!(r &= 7)) goto zeromemEXIT;
   and   edx, 7
   je   SHORT $zeromemEXIT$77849
   npad   6
$mem1SET$77850:
; 30   : mem1SET:
   mov   BYTE PTR [eax], 0
   add   eax, 1
; 32   :   if(--r) goto mem1SET;
   sub   edx, 1
   jne   SHORT $mem1SET$77850
$zeromemEXIT$77849:
   ret   0
@bnzeromem@8 ENDP
Qu'il est bien ce compilo quand il ne nout fait pas des trucs à l'insu de notre plein gré...

signaler à un administrateur
Commentaire de BruNews le 13/08/2006 00:40:44 administrateur CS

J'oubliais de préciser qu'ainsi on obtient un exe de 2 Ko.
Je remets le proj ici:
http://bnmvp.free.fr/nocrt.zip
ça permettra de vérifier les options de compilo et linker.

signaler à un administrateur
Commentaire de vecchio56 le 13/08/2006 14:36:27 administrateur CS

Je sais pas ce qu'a fait le compilo comme optimisation, c'est bizarre
Mais ta fonction bnzeromem est fausse, car en l'occurence avec une zone de 48 octets elle va boucler:
len >>= 3 donne 6, ensuite len -= 8 ne vaudra jamais 0

signaler à un administrateur
Commentaire de BruNews le 13/08/2006 14:44:24 administrateur CS

oups, c'est: if(--len) goto mem8SET;

signaler à un administrateur
Commentaire de vecchio56 le 13/08/2006 14:48:34 administrateur CS

Et voila, du coup le compilo nous sort un code potable:

@bnzeromem@8 PROC ; COMDAT
; _pmem$ = eax

; 20   :   BYTE *p = (BYTE*) pmem;
; 21   :   DWORD r = len;
; 22   :   if(!(len >>= 3)) goto prepm1SET;

mov ecx, 6
xor edx, edx
$mem8SET$77844:

; 23   : mem8SET:
; 24   :   *((DWORD*) p) = 0;

mov DWORD PTR [eax], edx

; 25   :   *((DWORD*) (p + 4)) = 0;

mov DWORD PTR [eax+4], edx

; 26   :   p += 8;

add eax, 8

; 27   :   if(--len) goto mem8SET;

sub ecx, 1
jne SHORT $mem8SET$77844
$prepm1SET$77843:
$zeromemEXIT$77849:

; 28   : prepm1SET:
; 29   :   if(!(r &= 7)) goto zeromemEXIT;
; 30   : mem1SET:
; 31   :   *p++ = 0;
; 32   :   if(--r) goto mem1SET;
; 33   : zeromemEXIT: return;
; 34   : }

ret 0
@bnzeromem@8 ENDP


Encore bien optimisé puisqu'il met direct un mov ecx, 6 et enlève toute la deuxième partie de l'algo.

signaler à un administrateur
Commentaire de BruNews le 13/08/2006 14:54:33 administrateur CS

moralité: pas de code après resto.

signaler à un administrateur
Commentaire de vecchio56 le 13/08/2006 18:53:59 administrateur CS

Nouvel épidose: j'utilise le code de racpp pour voir quelles sont les dépendances éventuelles.
J'ai cette fonction, pour remplacer memset
void MemSet(void* dst, int byte, int size)
{
  char* end = (char*)dst + size, *p;
  for(p = (char*)dst; p != end; *p++ = byte);
}
Si je mets les deux lignes en commentaire, rien
Si je laisse ces deux lignes: symbole externe non résolu _memset référencé dans la fonction _MemSet
Je n'ai pas de ZeroMemory ou autre choses du genre ailleurs dans mon code

Je trouve que le compilo prend vraiment trop libertés!

signaler à un administrateur
Commentaire de BruNews le 13/08/2006 19:03:21 administrateur CS

ça je l'ai déjà eu, si la signature complète de la fonction ressemble à une intégrée de la CRT, il met la sienne.
J'avais résolu en mettant du code asm en remplacement.

signaler à un administrateur
Commentaire de vecchio56 le 13/08/2006 19:40:30 administrateur CS

C'est incroyable ca! Il arrive a 'voir' que ma fonction fait la même chose que memset?

signaler à un administrateur
Commentaire de vecchio56 le 13/08/2006 19:52:29 administrateur CS

Autant les pb précédents sont plus ou moins expliqué, autant cette fois je comprends pas. Voici le code généré par ma fonction MemSet:

PUBLIC _MemSet
EXTRN _memset:PROC
; Function compile flags: /Ogtpy
; COMDAT _MemSet
_TEXT SEGMENT
_dst$ = 8 ; size = 4
_byte$ = 12 ; size = 4
_size$ = 16 ; size = 4
_MemSet PROC ; COMDAT

; 40   :   char* end = (char*)dst + size, *p;

mov ecx, DWORD PTR _dst$[esp-4]
mov eax, DWORD PTR _size$[esp-4]
add eax, ecx

; 41   :   for(p = (char*)dst; p != end; *p++ = byte);

cmp ecx, eax
je SHORT $LN3@MemSet
sub eax, ecx
mov DWORD PTR _size$[esp-4], eax
mov DWORD PTR _dst$[esp-4], ecx
jmp _memset
$LN3@MemSet:

; 42   : }

ret 0
_MemSet ENDP
_TEXT ENDS

Je ne pense pas que ce soit un pb de signature (même pb en inversant l'ordre des params)

Sinon t'aurais pas une bonne memset perso sous la main?

signaler à un administrateur
Commentaire de BruNews le 13/08/2006 19:55:47 administrateur CS

Il fait tellement plus fort, on ne va plus s'étonner de si peu.
Essaie la compil "profil guided optimization" et vérifie le listing asm à chaque étape, il déplace des bouts de code et réécrit si besoin pour gagner qlqs cycles, un truc de fou.
Me semble que G. Vollant a mis des trucs là dessus sur son site.

signaler à un administrateur
Commentaire de BruNews le 13/08/2006 20:00:10 administrateur CS

he he, tu as sentis venir ??? je démarrais justement une lib perso pour memset et memcpy, n'y aura plus qu'à mettre la lib dans dossier du proj et inclure son h.
Je vais faire 2 versions de chaque (enfin j'y réfléchis), aligné et non aligné.

signaler à un administrateur
Commentaire de racpp le 13/08/2006 20:33:38 administrateur CS

Salut,
Moi aussi j'ai remarqué ce petit problème. Le pire c'est que, dans le même code, certains appels à ma fonction se font normalement alors que d'autres sont remplacés par _memeset. J'ai résolu le problème en ajoutant /Ob1 aux options du compilateur. Je comprends pas trop mais ça marche.

signaler à un administrateur
Commentaire de racpp le 13/08/2006 20:39:52 administrateur CS

Voici la fonction que j'utilise:
void FillMem(void *destination, DWORD  longueur,BYTE octet)
{
// Obtenir un pointeur sur DWORD:
DWORD*  destination32=(DWORD*)destination;
// Calculer la taille en DWORDs:
DWORD taille32=longueur/4;
// Former un DWORD dont chaque octet contient la valeur de notre octet:
DWORD groupe=(octet*0x1000000 | octet*0x10000 | octet*0x100 | octet);
// Si la longueur est inférieure à 4 on met juste les octets qu'il faut:
switch (longueur-(taille32*2)) // astuce:
{
case 3: ((BYTE*)destination)[longueur-3] = octet;
case 2: ((BYTE*)destination)[longueur-2] = octet;
case 1: ((BYTE*)destination)[longueur-1] = octet;
}
// Remplir par notre DWORD tant que la taille est supérieure à 0:
while( taille32-- > 0 ) *(destination32++) = groupe;
}

Elle ne doit pas être aussi rapide que celle de Brunews, mais elle fonctionne très bien. Je la soumets à vos remarques.

signaler à un administrateur
Commentaire de racpp le 13/08/2006 20:49:01 administrateur CS

switch (longueur-(taille32*2)) // astuce: le bloc du switch n'accepte que les valeurs 3, 2 et 1. si taille32=1 (quand longueur=4) le resultat sera 3, ce qui faussera tout. On multiplie taille32 par 2 pour éviter ce cas.

signaler à un administrateur
Commentaire de BruNews le 13/08/2006 21:11:45 administrateur CS

C'est clair qu'il faut insérer 4 octets par passe.
Par contre faudra remplacer les multiplications, tu peux obtenir 'groupe' en 3 MOV.

signaler à un administrateur
Commentaire de racpp le 13/08/2006 21:18:44 administrateur CS

J'ai mis les multiplication juste pour la clarté du code. Normalement, le compilo les remplace par des décalages à gauche. Les 3 MOV c'est mieux?

signaler à un administrateur
Commentaire de BruNews le 13/08/2006 21:36:20 administrateur CS

décalages + 4 OR

Faisons que octet est dans AL et on met 'groupe' dans EAX:
mov ah, al
mov dx, ax
shl eax, 16
mov ax, dx
J'avais oublié un shl avec les 3 mov.

Comme d'hab, ne croyons rien et comparons, regarde ton listing asm et on sera certain de ce qui est préférable.

signaler à un administrateur
Commentaire de vecchio56 le 25/08/2006 20:57:21 administrateur CS

J'ai trouvé un autre moyen de régler ces problèmes de memset: carrément redéfinir memset
Au début le compilo ne veut pas (il dit fonction intrinsèque, non définissable)
J'ai trouvé qu'il faut juste mettre un pragma avant:
#pragma function(memset)
void* memset(void* buffer, int c, unsigned int num)
{
  // notre fonction memset
}

Ca nous permet de pouvoir écrire des {0} ou ZeroMemory par exemple et de ne pas changer nos habitudes

Mais cette solution a un gros onconvénient: elle est incompatible avec l'option /GL de compilo (optimisation globale du programme). On est alors obligé de la désactiver, et du coup /LTCG aussi

Finalement cette solution ne vaut pas le coup, mais je voulais juste vous signaler l'existence de ce pragma

signaler à un administrateur
Commentaire de HeavenForsaker le 26/06/2007 12:14:14

Bon idem pour moi, le compilo remplace mes fonctions perso par de la CRT, les voici :

char *asmemset(void *dest, int c, unsigned int count)
{
register char *st = (char *)dest;

while (count-- > 0)
*st++ = c;

return (char *)dest;
}
//------------------------------------------------------------------------------

char *asmemcpy(void *dest, const void *src, unsigned int count)
{
register char *des = (char *)dest;
register const char *sr = (const char *)src;

while (count-- > 0)
*des++ = *sr++;

return (char *)dest;
}
//------------------------------------------------------------------------------

int asmemcmp(const void *buf1, const void *buf2, unsigned int count)
{
register const char *b1 = (const char *)buf1;
register const char *b2 = (const char *)buf2;

while (count-- > 0)
{
if (*b1++ != *b2++)
return b1[-1] < b2[-1] ? -1 : 1;
}

return 0;
}
//------------------------------------------------------------------------------

Est ce que par hasard vous auriez un set de fonction que le compilo ne detecte pas comme étant similaire a celle de la CRT ?
Tu disais BruNews que tes fonction asm n'était pas détectée ? pourrais tu publier tes fonctions ? j'ai juste besoin de ces 3 la , memcpy, memset et memcmp.

signaler à un administrateur
Commentaire de HeavenForsaker le 26/06/2007 13:50:16

Rectification, seul ma fonction asmemset est détectée et remplacée par memset, les 2 autres sont bonnes.

Aller BruNews fait péter memset en ASM ! :-)

signaler à un administrateur
Commentaire de BruNews le 26/06/2007 17:21:44 administrateur CS

trop lent par octet.
Versions pour buffers alignés ou non. Utiliser les 'AL' quand tu es certain de l'alignement sur 4 de destination (souvent le cas dans code propre).

void __fastcall bnzeromemAL(void *pmem, DWORD len)
{
  BYTE *p = (BYTE*) pmem;
  DWORD r = len;
  if(!(len >>= 3)) goto prepm1SET;
mem8SET:
  *((DWORD*) p) = 0;
  *((DWORD*) (p + 4)) = 0;
  p += 8;
  if(--len) goto mem8SET;
prepm1SET:
  if(!(r &= 7)) goto zeromemEXIT;
mem1SET:
  *p++ = 0;
  if(--r) goto mem1SET;
zeromemEXIT: return;
}

void __fastcall bnzeromemUNAL(void *pmem, DWORD len)
{
  BYTE *p = (BYTE*) pmem;
  DWORD r;
  if(!len) goto zeromemEXIT;
  r = ((DWORD) p) & 3;
  if(!r) goto okALIGN;
  *p++ = 0;
  if(--len == 0) goto zeromemEXIT;
  if(--r == 0) goto okALIGN;
  *p++ = 0;
  if(--len == 0) goto zeromemEXIT;
  if(--r == 0) goto okALIGN;
  *p++ = 0;
  if(--len == 0) goto zeromemEXIT;
okALIGN:
  r = len;
  if(!(len >>= 3)) goto prepm1SET;
mem8SET:
  *((DWORD*) p) = 0;
  *((DWORD*) (p + 4)) = 0;
  p += 8;
  if(--len) goto mem8SET;
prepm1SET:
  if(!(r &= 7)) goto zeromemEXIT;
mem1SET:
  *p++ = 0;
  if(--r) goto mem1SET;
zeromemEXIT: return;
}

__declspec(naked) void __fastcall bnfillmemAL(void *pmem, BYTE v, DWORD len)
{ // ECX = pmem, EDX = v, [esp+4] = len
  __asm {
    mov     eax, ecx        ; EAX = pmem
    and     edx, 0FFh       ; octet seul
    mov     ecx, [esp+4]    ; ECX = len
    mov     [esp-8], esi
    mov     [esp-4], ebx
    mov     dh, dl
    test    ecx, ecx
    je      short fillEXIT
    mov     esi, ecx
    mov     ebx, edx
    shr     ecx, 3
    je      short prepf1SET
    shl     edx, 16
    mov     dx, bx
f8SET:
    mov     [eax], edx
    mov     [eax+4], edx
    add     eax, 8
    sub     ecx, 1
    jnz     short f8SET
prepf1SET:
    and     esi, 7
    je      short fillCLEAN
f1SET:
    mov     [eax], dl
    add     eax, 1
    sub     esi, 1
    jnz     short f1SET
fillCLEAN:
    mov     ebx, [esp-4]
    mov     esi, [esp-8]
fillEXIT:
    ret   4
  }
}

__declspec(naked) void __fastcall bnfillmemUNAL(void *pmem, BYTE v, DWORD len)
{ // ECX = pmem, EDX = v, [esp+4] = len
  __asm {
    mov     eax, ecx        ; EAX = pmem
    and     edx, 0FFh       ; octet seul
    mov     ecx, [esp+4]    ; ECX = len
    mov     [esp-8], esi
    mov     [esp-4], ebx
    mov     dh, dl
    test    ecx, ecx
    je      short fillEXIT
    mov     ebx, eax
    and     ebx, 3
    je      short okALIGN
    mov     [eax], dl
    add     eax, 1
    sub     ecx, 1
    jz      short fillCLEAN
    sub     ebx, 1
    jz      short okALIGN
    mov     [eax], dl
    add     eax, 1
    sub     ecx, 1
    jz      short fillCLEAN
    sub     ebx, 1
    jz      short okALIGN
    mov     [eax], dl
    add     eax, 1
    sub     ecx, 1
    jz      short fillCLEAN
okALIGN:
    mov     esi, ecx
    mov     ebx, edx
    shr     ecx, 3
    je      short prepf1SET
    shl     edx, 16
    mov     dx, bx
f8SET:
    mov     [eax], edx
    mov     [eax+4], edx
    add     eax, 8
    sub     ecx, 1
    jnz     short f8SET
prepf1SET:
    and     esi, 7
    je      short fillCLEAN
f1SET:
    mov     [eax], dl
    add     eax, 1
    sub     esi, 1
    jnz     short f1SET
fillCLEAN:
    mov     ebx, [esp-4]
    mov     esi, [esp-8]
fillEXIT:
    ret   4
  }
}

signaler à un administrateur
Commentaire de BruNews le 26/06/2007 19:39:59 administrateur CS

Marrant quand un sujet revient sur le devant de la scène...

Je viens d'ajouter ceci (entre autre) dans mon taf en cours:
JJ = pcurrArts->dateF - pPLAN[0];
if(JJ < 0) JJ = 0;
for(; JJ < NCOLS; JJ++) TPLANAR.jours[JJ] = 0;
ben il m'a remplacé la boucle par un: call memset
pénible...

signaler à un administrateur
Commentaire de HeavenForsaker le 26/06/2007 22:45:00

Cool merci BruNews ! j'ai plus le vilain message CRT :-)

J'avais un autre message quand j'avais mis "Ignore All Default Libraries" à yes :
error LNK2001: unresolved external symbol __chkstk

Pour ceux qui l'ont eu c'est à cause d'un buffer trop gros, j'en avait un a 768 WCHAR je l'ai descendu a 256 et plus de message même avec cette option activée.

signaler à un administrateur
Commentaire de HeavenForsaker le 27/06/2007 16:26:03

J'ai regardé ta fonction bnzeromemAL de pret la, c'est du bon, par contre quand tu dit "Utiliser les 'AL' quand tu es certain de l'alignement sur 4 de destination" tu veux dire aligner sur 4 octets ? parce que la ça serais plutot 8 puisque tu efface 8 par passe :
  *((DWORD*) p) = 0;
  *((DWORD*) (p + 4)) = 0;

signaler à un administrateur
Commentaire de BruNews le 27/06/2007 17:17:39 administrateur CS

alignement sur une adresse multiple de 4 puisqu'on adressera par 4 octets.
C'est visible ici:
r = ((DWORD) p) & 3;

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

font dans mon fichier ressource [ par nipower ] Bonjour je travail avec Dev-c++ et j'ai besoin dans mon projet d'intégrer une police spéciale et non standard.Le problème et que je n'arrive pas à uti police et ListBox [ par JeriKo ] salut à tousça fait 2 heures que j'essaye de changer la police de ma listbox, y a rien à faire ça veut pas :(alors j'ai fait comme çaCListBox *list FOnt & police [ par youpiyoyo ] voila j'utilise caSetBkMode(dc, TRANSPARENT); SetTextColor(dc,clrB); //BeginPath(dc); TextOut(dc,(FreeImage_GetWidth(dibe)/2),FreeImage_GetHeight(dibe CreateFont + SetFont + font asia [ par drexi ] Mon application doit etre compatible pour un affichage sur un PC chinois...Le code créé automatiquement (Bouton Next d'une CPropertySheet est bien aff police en ressource [VC6] [ par leprov ] cest possible de mettre une police en ressource? c'est pitetre con comme question mais j'ai pas trop l'habitude de l'éditeur de ressources, et je sais problème police openGl [ par vodkapomme43 ] Bonjour,J'utilise le code suivant pour cr&#233;er une police avec OPenGL:GLvoid BuildFont(GLvoid)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Bu Messagebox et police VC++(pas de MFC) [ par Frenchy62620 ] Une question concernant la messagebox est ce q'uon peut modifier la font de la messagebox avant son affichage? (juste la font de cet objet)Frenchy Creer une ressource avec Borland builder6 [ par popi0016 ] Bonjours je voudrais associer a mon .exe des images (bmp ou jpeg) et aimerai savoir comment creer une ressource avec toutes mes images (60 environs) s C++! [ par Chaminouonw ] Bonjour je suis débutant en c++ et j'aimerais avoir des ressources pour commencer, étant donné que je ne m'y connais absolument pas dans ce milieu, je Fonction et Tableau [ par toff86 ] Salut !!J'suis débutant en C. Mon probleme est le suivant:Je sais comment fonctionne le passage de parametres d'une variable avec les foncions. Mais j


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,468 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.