Convertir la bibliothèque Windows statique en dll

J’ai une bibliothèque contenant un tas de fichiers statiques *lib , je souhaite y accéder depuis JNA (une librairie Java qui permet d’appeler dynamicment `dll ‘depuis JAVA Code), alors est-il possible de changer magiquement la lib statique en dll?

Le code a été compilé à l’aide de Visual Studio (en espérant que cela soit pertinent) et j’ai également des fichiers d’en-tête appropriés.

Je n’ai pas access au code source, mais je voudrais aussi le faire en utilisant uniquement des outils gratuits (comme dans la bière).

Je ne connais pas les outils anyb qui le feront automatiquement, mais le processus consiste à créer un projet DLL et à append vos bibliothèques au projet. Pour chaque fonction du fichier d’en-tête:

 int SomeLibFunc( int x, int y ); 

vous devez créer et exporter votre propre fonction dans la DLL;

 int MyFunc( int x, int y ) { return SomLibFunc( x, y ); } 

Le processus est assez mécanique et vous pouvez créer un script utilisant quelque chose comme perl pour créer les fichiers source DLL.

En supposant que vous n’ayez pas access à la source, vous pouvez simplement créer une DLL wrapper qui exporte les fonctions dont vous avez besoin et délègue la bibliothèque statique.

J’ai fait comme anon suggéré, j’ai fait un convertisseur automatique (quelqu’un a suggéré de mettre _ddlspec (export) avant la déclaration et de comstackr dll avec cet en-tête fonctionnerait – eh bien ça n’a pas été – j’ai fait quelque chose de mal – Ancien programmeur Java;)):

il parsing essentiellement les fichiers d’en-tête et tourne:

  SADENTRY SadLoadedMidFiles( HMEM, USHORT usMaxMidFiles, VOID * ); 

à:

  __declspec(dllexport) SADENTRY DLL_WRAPPER_SadLoadedMidFiles(HMEM param0, USHORT usMaxMidFiles, VOID* param2){ return SadLoadedMidFiles(param0, usMaxMidFiles, param2); } 

Voici le code (très probablement son abus de Regexp, mais ça marche), la partie gui dépend de MigLayout:

  package cx.ath.jbzdak.diesIrae.util.wrappergen; import net.miginfocom.swing.MigLayout; import javax.swing.*; import static java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.*; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Displays a window. In this window you have to specify two things: * 

* 1. Name of header file that you want to process. *

* 2. Name of output files extension will be added automatically. We will override any existing files. * *

* Dependencies: MigLayout *

* Actual wrapper generation is done inside WrapperGen class. *

* KNOWN ISSUES: *

* 1. Ignores preprocessor so may extract finction names that are inside
#if false. *

* 2. Ignores comments *

* 3. May fail to parse werid parameter syntax. . . * * Created by IntelliJ IDEA. * User: Jacek Bzdak */ public class WrapperGenerator { public static final Charset charset = Charset.forName("UTF-8"); WrapperGen generator = new WrapperGen(); // GUI CODE: File origHeader, targetHeader, targetCpp; JTextField newHeaderFileName; JFrame wrapperGeneratorFrame; { wrapperGeneratorFrame = new JFrame(); wrapperGeneratorFrame.setTitle("Zamknij mnie!"); //Wrapper generator wrapperGeneratorFrame.setLayout( new MigLayout("wrap 2, fillx", "[fill,min!]")); wrapperGeneratorFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ActionListener buttonListener = new ActionListener() { JFileChooser fileChooser = new JFileChooser(); { fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() { @Override public boolean accept(File f) { return f.isDirectory() || f.getName().matches(".*\\.h(?:pp)?"); } @Override public Ssortingng getDescription() { return "Header files"; } }); fileChooser.setCurrentDirectory(new File("C:\\Documents and Settings\\jb\\My Documents\\Visual Studio 2008\\Projects\\dll\\dll")); } public void actionPerformed(ActionEvent e) { if(JFileChooser.APPROVE_OPTION == fileChooser.showOpenDialog(wrapperGeneratorFrame)){ origHeader = fileChooser.getSelectedFile(); } } }; wrapperGeneratorFrame.add(new JLabel("Original header file")); JButton jButton = new JButton("Select header file"); jButton.addActionListener(buttonListener); wrapperGeneratorFrame.add(jButton); wrapperGeneratorFrame.add(new JLabel("Result files prefix")); newHeaderFileName = new JTextField("dll_wrapper"); wrapperGeneratorFrame.add(newHeaderFileName); ActionListener doListener = new ActionListener() { public void actionPerformed(ActionEvent e) { targetHeader = new File(origHeader.getParentFile(), newHeaderFileName.getText() + ".h"); targetCpp = new File(origHeader.getParentFile(), newHeaderFileName.getText() + ".cpp"); try { targetHeader.createNewFile(); targetCpp.createNewFile(); generator.reader = new InputStreamReader(new FileInputStream(origHeader),charset); generator.cppWriter = new OutputStreamWriter(new FileOutputStream(targetCpp), charset); generator.heaerWriter = new OutputStreamWriter(new FileOutputStream(targetHeader), charset); generator.parseReader(); } catch (IOException e1) { e1.printStackTrace(); JOptionPane.showMessageDialog(wrapperGeneratorFrame, "ERROR:" + e1.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); return; } } }; JButton go = new JButton("go"); go.addActionListener(doListener); wrapperGeneratorFrame.add(go, "skip 1"); } public static void main(Ssortingng []args){ SwingUtilities.invokeLater(new Runnable() { public void run() { WrapperGenerator wgen = new WrapperGenerator(); JFrame f = wgen.wrapperGeneratorFrame; wgen.wrapperGeneratorFrame.pack(); Point p = getLocalGraphicsEnvironment().getCenterPoint(); wgen.wrapperGeneratorFrame.setLocation(px-f.getWidth()/2, py-f.getHeight()/2); wgen.wrapperGeneratorFrame.setVisible(true); } }); } } /** * Does the code parsing and generation */ class WrapperGen{ /** * Method is basically syntax like this: (anything apart from some special chars like #;) functionName(anything); * Method declarations may span many lines. */ private static final Pattern METHOD_PATTERN = //1 //2 //params Pattern.comstack("([^#;{}]*\\s+\\w[\\w0-9_]+)\\(([^\\)]*)\\);", Pattern.MULTILINE); //1 - specifiers - including stuff like __dllspec(export)... //2 - function name //3 param list /** * Generated functions will have name prefixet with #RESULT_PREFIX */ private static final Ssortingng RESULT_PREFIX = "DLL_WRAPPER_"; /** * Specifiers of result will be prefixed with #RESULT_SPECIFIER */ private static final Ssortingng RESULT_SPECIFIER = "__declspec(dllexport) "; Reader reader; Writer heaerWriter; Writer cppWriter; public void parseReader() throws IOException { SsortingngWriter writer = new SsortingngWriter(); int read; while((read = reader.read())!=-1){ writer.write(read); } reader.close(); heaerWriter.append("#pragma once\n\n\n"); heaerWriter.append("#include \"stdafx.h\"\n\n\n"); //Standard Visual C++ import file. cppWriter.append("#include \"stdafx.h\"\n\n\n"); Matcher m = METHOD_PATTERN.matcher(writer.getBuffer()); while(m.find()){ System.out.println(m.group()); handleMatch(m); } cppWriter.close(); heaerWriter.close(); } public void handleMatch(Matcher m) throws IOException { Method meth = new Method(m); outputHeader(meth); outputCPP(meth); } private void outputDeclaration(Method m, Writer writer) throws IOException { //writer.append(RESULT_SPECIFIER); writer.append(m.specifiers); writer.append(" "); writer.append(RESULT_PREFIX); writer.append(m.name); writer.append("("); for (int ii = 0; ii < m.params.size(); ii++) { Parameter p = m.params.get(ii); writer.append(p.specifiers); writer.append(" "); writer.append(p.name); if(ii!=m.params.size()-1){ writer.append(", "); } } writer.append(")"); } public void outputHeader(Method m) throws IOException { outputDeclaration(m, heaerWriter); heaerWriter.append(";\n\n"); } public void outputCPP(Method m) throws IOException { cppWriter.append(RESULT_SPECIFIER); outputDeclaration(m, cppWriter); cppWriter.append("{\n\t"); if (!m.specifiers.contains("void") || m.specifiers.matches(".*void\\s*\\*.*")) { cppWriter.append("return "); } cppWriter.append(m.name); cppWriter.append("("); for (int ii = 0; ii < m.params.size(); ii++) { Parameter p = m.params.get(ii); cppWriter.append(p.name); if(ii!=m.params.size()-1){ cppWriter.append(", "); } } cppWriter.append(");\n"); cppWriter.append("}\n\n"); } } class Method{ private static final Pattern NAME_REGEXP = //1 //2 Pattern.compile("\\s*(.*)\\s+(\\w[\\w0-9]+)\\s*", Pattern.MULTILINE); //1 - all specifiers - including __declspec(dllexport) and such ;) //2 - function name public final List params; public final Ssortingng name; public final Ssortingng specifiers; public Method(Matcher m) { params = Collections.unmodifiableList(Parameter.parseParamList(m.group(2))); Matcher nameMather = NAME_REGEXP.matcher(m.group(1)); System.out.println("ALL: " + m.group()); System.out.println("G1: " + m.group(1)); if(!nameMather.matches()){ throw new IllegalArgumentException("for ssortingng " + m.group(1)); } // nameMather.find(); specifiers = nameMather.group(1); name = nameMather.group(2); } } class Parameter{ static final Pattern PARAMETER_PATTERN = //1 //2 Pattern.comstack("\\s*(?:(.*)\\s+)?([\\w\\*&]+[\\w0-9]*[\\*&]?)\\s*"); //1 - Most probably parameter type and specifiers, but may also be empty - in which case name is empty, and specifiers are in 2 //2 - Most probably parameter type, sometimes prefixed with ** or &* ;), also // 'char *' will be parsed as grup(1) == char, group(2) = *. /** * Used to check if group that represenrs parameter name is in fact param specifier like '*'. */ static final Pattern STAR_PATTERN = Pattern.comstack("\\s*([\\*&]?)+\\s*"); /** * If */ static final Pattern NAME_PATTERN = Pattern.comstack("\\s*([\\*&]+)?(\\w[\\w0-9]*)\\s*"); public final Ssortingng name; public final Ssortingng specifiers; public Parameter(Ssortingng param, int idx) { System.out.println(param); Matcher m = PARAMETER_PATTERN.matcher(param); Ssortingng name = null; Ssortingng specifiers = null; if(!m.matches()){ throw new IllegalStateException(param); } name = m.group(2); specifiers = m.group(1); if(specifiers==null || specifiers.isEmpty()){ //Case that parameter has no name like 'int', or 'int**' specifiers = name; name = null; }else if(STAR_PATTERN.matcher(name).matches()){ //Case that parameter has no name like 'int *' specifiers += name; name = null; }else if(NAME_PATTERN.matcher(name).matches()){ //Checks if name contains part of type like '**ptrData', and extracts '**' Matcher m2 = NAME_PATTERN.matcher(name); m2.matches(); if(m2.group(1)!=null){ specifiers += m2.group(1); name = m2.group(2); } } if(name==null){ name = "param" + idx; } this.specifiers = specifiers; this.name = name; } public static List parseParamList(Ssortingng paramList){ List result = new ArrayList(); Ssortingng[] params = paramList.split(","); int idx = 0; for(Ssortingng param : params){ Parameter p = new Parameter(param, idx++); result.add(p); } if(result.size()==1){ Parameter p = result.get(0); if(p.specifiers.matches("\\s*void\\s*")){ return Collections.emptyList(); } } return result; } }