Je prévois de coder une bibliothèque qui devrait pouvoir être utilisée par un grand nombre de personnes sur un large éventail de plates-formes. Que dois-je considérer pour le concevoir correctement? Pour rendre ces questions plus spécifiques, il y a quatre “sous-questions” à la fin.
Compte tenu de toutes les exigences et de tous les détails connus, j’ai conclu qu’une bibliothèque écrite en C ou C ++ était la solution. Je pense que l’utilisation principale de ma bibliothèque sera dans les programmes écrits en C, C ++ et Java SE , mais je peux aussi penser à des raisons de l’utiliser depuis Java ME, PHP, .NET, Objective C, Python, Ruby, etc … Peut-être que je ne peux pas tous les cibler, mais si c’est possible, je le ferai.
Ce serait trop pour décrire le but de ma bibliothèque ici, mais certains aspects pourraient être importants pour cette question:
Bien sûr, les réponses sont les bienvenues, peu importe si elles répondent à mes exigences spécifiques ou si elles répondent à la question d’une manière générale qui compte pour un public plus large!
Voici donc certaines de mes hypothèses et conclusions, que j’ai rassemblées au cours des derniers mois:
Surtout correct L’interface de procédure droite est la meilleure. (qui n’est pas tout à fait identique à C btw (**), mais suffisamment proche)
J’interface beaucoup les DLL (*), à la fois open source et commerciales, alors voici quelques points dont je me souviens dans la pratique quotidienne, notez qu’il s’agit de domaines de recherche plus recommandés, et non de vérités cardinales:
(**) C’est parce que “C” signifie que le binary dépend toujours du compilateur C utilisé, surtout s’il n’y a pas de véritable ABI universel. Pensez à des choses comme:
===== conversions d’en-tête automatisées ====
Bien que je ne connaisse pas bien SWIG, je connais et utilise des outils d’en-tête spécifiques à Delphi (h2pas, Darth / headconv, etc.).
Cependant, je ne les utilise jamais en mode entièrement automatique, car le plus souvent, la sortie ne craint pas. Les commentaires changent de ligne ou sont supprimés et le formatage n’est pas conservé.
Je fais généralement un petit script (en Pascal, mais vous pouvez utiliser n’importe quel support de chaîne décent) pour séparer un en-tête et essayer un outil sur des parties relativement homogènes (par exemple, uniquement des structures, ou seulement des définitions, etc.).
Ensuite, je vérifie si j’aime la sortie de conversion automatisée, et je l’utilise ou j’essaie de créer un convertisseur spécifique. Comme il s’agit d’un sous-ensemble (comme seules les structures), il est souvent beaucoup plus facile de créer un convertisseur d’entête complet. Bien sûr, cela dépend un peu de ma cible. (belles en-têtes lisibles ou rapides et sales). À chaque étape, je pourrais faire quelques substitutions (avec sed ou un éditeur).
Le schéma le plus compliqué que j’ai fait pour les en-têtes Winapi commctrl et ActiveX / comctl. Là, j’ai combiné l’en-tête C et IDL (IDL pour les interfaces, qui sont un tas de macros non analysables en C, l’en-tête C pour le rest), et réussi à obtenir les macros typées pour environ 80% les macros de retour à la déclaration de macro, avec des valeurs par défaut raisonnables (wparam, lparam, lresult))
Le mode semi-automatisé présente l’inconvénient que l’ordre des déclarations est différent (par exemple, les premières constantes, puis les structures, puis les déclarations de fonction), ce qui rend parfois difficile la maintenance. Je garde donc toujours les en-têtes / sdk originaux à comparer.
Le projet de conversion Jedi Winapi pourrait avoir plus d’informations, ils ont traduit environ la moitié des en-têtes Windows à Delphi et ont donc une énorme expérience.
Je ne sais pas, mais si c’est pour Windows, vous pouvez essayer soit une API de type C (similaire à WINAPI), soit empaqueter votre code en tant que composant COM, car je suppose que les langages de programmation peuvent vouloir être invoquer l’API Windows et / ou utiliser des objects COM.
En ce qui concerne la génération automatique de wrapper, envisagez d’utiliser SWIG. Pour Java, il fera tout le travail de JNI. En outre, il est capable de traduire correctement les interfaces OO-C ++ complexes (à condition de suivre certaines directives de base, à savoir pas de classes nestedes, pas de surutilisation des modèles, plus ceux mentionnés par Marco van de Voort).
Pensez C, rien d’autre. C est l’un des langages de programmation les plus populaires. Il est largement utilisé sur de nombreuses plates-formes logicielles et il existe peu d’architectures informatiques pour lesquelles aucun compilateur C n’existe. Tous les langages de haut niveau populaires fournissent une interface à C. Cela rend votre bibliothèque accessible à partir de presque toutes les plates-formes existantes. Ne vous souciez pas trop de fournir une interface orientée object. Une fois que vous avez fait la bibliothèque en C, OOP, une interface fonctionnelle ou toute autre interface de style peut être créée dans les langages client appropriés. Aucun autre langage de programmation de systèmes ne vous donnera la flexibilité et la puissance de C.
Je pense que NestedVM sera plus lent que Java en raison des limites du tableau vérifiant l’int [] [] qui représente la mémoire de la machine virtuelle MIPS. C’est un si bon concept, mais il se peut qu’il ne fonctionne pas assez bien (jusqu’à ce que les fabricants de téléphones ajoutent le support NestedVM (s’ils le font!), La plupart des choses vont être SLOW pour le moment, n’est-ce pas)? Bien qu’il soit possible de décompresser les fichiers JPEG sans erreur, la vitesse n’est pas un problème! 🙂
Rien d’autre dans ce que vous avez écrit, ce qui ne veut pas dire que c’est vrai ou faux! Les principes retentissent (principalement en écoutant le choix des mots et de la langue pour être honnête) comme les meilleures pratiques à peu près standard mais je n’ai pas réfléchi aux détails de tout ce que vous avez dit. Comme vous l’avez dit vous-même, cela devrait être plusieurs questions. Mais bien sûr, ce genre de chose n’est pas automatiquement simple parce que vous êtes peut-être fixé sur une architecture légèrement différente du dernier code sur lequel vous avez travaillé…! 😉
Mes pensées:
Tous vos commentaires sur la compatibilité des interfaces C me semblent judicieux, à part les bonnes pratiques, sauf que vous ne semblez pas traiter correctement les règles de gestion de la mémoire – certaines phrases un peu ambiguës / vagues / fausses. La conception de la gestion de la mémoire sera dans une large mesure déterminée par les modèles d’access définis dans votre application, plutôt que par les fonctionnalités en soi. Je pense que vous étudiez attentivement les tentatives des autres utilisateurs pour créer des interfaces portables telles que l’API ANSI C standard, l’API Unix, l’API Win32, Cocoa, J2SE, etc.
Si c’était moi, j’écrirais la bibliothèque dans un sous-ensemble soigneusement choisi des éléments communs de Java et de la machine virtuelle Java de Davlik et j’écrirais mon propre parsingur personnalisé qui traduirait le code en C pour les plates-formes qui supportent C, ce qui bien sûr être la plupart d’entre eux. Je suggère que si vous vous limitez à des types de données de tailles différentes ints, bools, Ssortingngs, Dictionaries et Arrays et que vous les utilisiez avec précaution, cela vous aidera dans la plupart des cas sans affecter les performances.
vos suppositions semblent correctes, mais je vois des problèmes à l’avenir, dont la plupart ont déjà été repérés dans vos hypothèses. Comme vous l’avez dit, vous ne pouvez pas vraiment exporter les classes et les méthodes c ++, vous devrez fournir une interface basée sur les fonctions. Quelle que soit la façade que vous construisez autour de cela, elle restra une interface basée sur les fonctions à cœur.
Le problème de base que je vois avec cela est que les gens choisissent une langue spécifique et son exécution parce que leur façon de penser (fonctionnelle ou orientée object) ou le problème auquel ils s’adressent (programmation Web, firebase database,…) correspond à cette langue. ou autre. Une bibliothèque implémentée dans c ne se sentira probablement jamais comme les bibliothèques auxquelles elle est habituée, à moins qu’elle ne programme elle-même en c. Personnellement, je préférerais toujours une bibliothèque qui “ressemble à Python” quand j’utilise Python, et une bibliothèque qui ressemble à Java quand je fais Java EE, même si je connais c et c ++.
Ainsi, vos efforts pourraient être peu utiles (autres que votre expérience), car les utilisateurs voudront probablement restr fidèles à leur état d’esprit et ré-implémenter la fonctionnalité plutôt que d’utiliser une bibliothèque qui fait le travail, mais qui ne convient pas.
Je crains également que la portabilité souhaitée ne nuise sérieusement au développement. Pensez simplement aux parameters de construction infinis nécessaires et testez-les. J’ai travaillé sur un projet qui essayait de maintenir la compatibilité pour 5 systèmes d’exploitation (tous de type posix, mais quand même) et environ 10 compilateurs, les versions étant un cauchemar à tester et à maintenir.
Donnez-lui une interface XML, qu’elle soit transmise en tant que paramètre et valeur de retour ou en tant que fichiers via un appel de ligne de commande. Cela peut ne pas sembler aussi direct qu’une interface de fonction normale, mais c’est le moyen le plus pratique d’accéder à un exécutable à partir, par exemple, de Java.