www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - CTFE and -betterC

reply Xavier Bigand <flamaros.xavier gmail.com> writes:
As I am trying to do a dll that acts exactly like one written in C, I am trying
to compile my code with the -betterC option. So I would not need the DllMain
function.

I am not sure that I use the best syntax for my CTFE function to be able to
make it works with the option -betterC and to maintain it after.

In particular I have following issues (my code is at the end of message) :
  * startsWith function doesn't compile with -betterC
  * can't put static before the first foreach
  * don't really now how to factorize small expressions (oglFunctionName ,
oglFunctionName,...)
  * how to make the code I generate less polluted by conditions and iterations?
Certainly by naming some previously computed parts with alias?
  * after that how to see the generated result and debug?

Thank you in advance for any help.

module api_entry;

import std.stdio : writeln;
import std.algorithm.searching;

import missing_ogl;

import std.traits;
import std.meta;

static string implementFunctionsOf(string Module, bool removeARB = false)()
{
     import std.traits;
     import std.regex;
     import std.conv;

     mixin("import " ~ Module ~ ";");

     string	res;

     res ~= "extern (C) {\n";

     foreach (name; __traits(allMembers, mixin(Module)))
     {
         static if (name.startsWith("da_")
                    && mixin("isCallable!" ~ name))
         {
             alias derelict_oglFunctionName = Alias!(name[3..$]);
             alias oglFunctionName = derelict_oglFunctionName;
             alias returnType = Alias!(ReturnType!(mixin(name)).stringof);
             alias parametersType = Alias!(Parameters!(mixin(name)).stringof);

             static if (removeARB && name.endsWith("ARB"))
                 oglFunctionName = oglFunctionName[0..$ - 3];

             res ~=
                 "export\n" ~
                 returnType ~ "\n" ~
                 oglFunctionName ~
                 parametersType ~ "\n" ~
                 "{\n" ~
                 "    writeln(\"" ~ oglFunctionName ~ " is not
specialized\");\n";

             // Forward the call to the driver (with arguments and return the
             // value of the forward directly)
             res ~= "import " ~ Module ~ ";";

             // For a reason I do not understand the compiler can not
             // compile with returnType
             static if (ReturnType!(mixin(name)).stringof == "int function()")
                 res ~=
                     "    alias extern (C) " ~ returnType ~ " returnType;\n" ~
                     "    return cast(returnType) ";
             else if (returnType != "void")
                 res ~=
                     "    return ";
             res ~=
                 "    " ~ Module ~ "." ~ derelict_oglFunctionName ~ "(";
             foreach (i, parameter; Parameters!(mixin(name)))
             {
                 if (i > 0)
                     res ~= ", ";
				// We use the default parameter name variable "_param_x" where x
				// is the index of the parameter starting from 0
                 res ~= "_param_" ~ to!string(i);
             }
             res ~=
                 ");";

             res ~=
                 "}\n";
         }
     }

     res ~=
         "}\n";
     return res;
}


mixin(implementFunctionsOf!("derelict.opengl3.functions"));
mixin(implementFunctionsOf!("derelict.opengl3.deprecatedFunctions"));
Mar 13 2018
parent reply rikki cattermole <rikki cattermole.co.nz> writes:
You will still need DllMain, that is a platform requirement.
Mar 13 2018
parent reply Flamaros <flamaros.xavier gmail.com> writes:
On Wednesday, 14 March 2018 at 01:17:54 UTC, rikki cattermole 
wrote:
 You will still need DllMain, that is a platform requirement.
I am not sure about that because when DllAnalyser don't see it in the opengl32.dll from the system32 directory. And the documentation indicate that it is optional. I finally choose to put the entry points generation in a sub-project that put them in a d file, like that it is easier to make the CTFE working and will be much better for the debugging and compilation time. So I have also some few other questions : - Is it a bug that ctRegex doesn't with the return of allMembers? - What is the status of the new CTFE engine? - Will CTFE be able to write files or expose a way to see to resulting generated code for a debug purpose? - Is there a reason why CTFE is impacted by the -betterC option?
Mar 14 2018
parent reply Xavier Bigand <flamaros.xavier gmail.com> writes:
Le 15/03/2018 à 01:09, Flamaros a écrit :
 On Wednesday, 14 March 2018 at 01:17:54 UTC, rikki cattermole wrote:
 You will still need DllMain, that is a platform requirement.
I am not sure about that because when DllAnalyser don't see it in the opengl32.dll from the system32 directory. And the documentation indicate that it is optional. I finally choose to put the entry points generation in a sub-project that put them in a d file, like that it is easier to make the CTFE working and will be much better for the debugging and compilation time. So I have also some few other questions : - Is it a bug that ctRegex doesn't with the return of allMembers? - What is the status of the new CTFE engine? - Will CTFE be able to write files or expose a way to see to resulting generated code for a debug purpose? - Is there a reason why CTFE is impacted by the -betterC option?
I actually found token strings, but I can't figure out how to cascade them, it is even possible? I tried things like that : enum loadSystemSymbolsCode = q{ version (Windows) { extern (Windows) void loadSytemSymbols() { import core.sys.windows.windows; immutable string dllFilePath = "C:/Windows/System32/opengl32.dll"; auto hModule = LoadLibraryEx(dllFilePath, null, 0); if (hModule == null) { return; } writeln(dllFilePath ~ " loaded."); "%SYSTEM_BINDINGS%" } } }; enum moduleCode = q{ module api_entry; import std.stdio : writeln; import derelict.util.wintypes; export extern (C) { mixin(loadSystemSymbolsCode); } }; string getLoadSystemSymbolsCode(string bindinsCode)() { return loadSystemSymbolsCode.replace("%SYSTEM_BINDINGS%", bindinsCode); } string getModuleCode(string loadSystemSymbolsCode)() { return moduleCode.replace("%LOAD_SYSTEM_SYMBOLS%", loadSystemSymbolsCode); } void main() { import std.stdio : File; auto file = File("../opengl32/src/api_entry.d", "w"); file.writeln( getModuleCode!( getLoadSystemSymbolsCode!("test;")()) ); } Is there some materials for learning to do this kind of things with CTFE?
Mar 16 2018
parent Xavier Bigand <flamaros.xavier gmail.com> writes:
Le 16/03/2018 à 22:58, Xavier Bigand a écrit :
 Le 15/03/2018 à 01:09, Flamaros a écrit :
 On Wednesday, 14 March 2018 at 01:17:54 UTC, rikki cattermole wrote:
 You will still need DllMain, that is a platform requirement.
I am not sure about that because when DllAnalyser don't see it in the opengl32.dll from the system32 directory. And the documentation indicate that it is optional. I finally choose to put the entry points generation in a sub-project that put them in a d file, like that it is easier to make the CTFE working and will be much better for the debugging and compilation time. So I have also some few other questions : - Is it a bug that ctRegex doesn't with the return of allMembers? - What is the status of the new CTFE engine? - Will CTFE be able to write files or expose a way to see to resulting generated code for a debug purpose? - Is there a reason why CTFE is impacted by the -betterC option?
I actually found token strings, but I can't figure out how to cascade them, it is even possible? I tried things like that : enum loadSystemSymbolsCode = q{ version (Windows) { extern (Windows) void loadSytemSymbols() { import core.sys.windows.windows; immutable string dllFilePath = "C:/Windows/System32/opengl32.dll"; auto hModule = LoadLibraryEx(dllFilePath, null, 0); if (hModule == null) { return; } writeln(dllFilePath ~ " loaded."); "%SYSTEM_BINDINGS%" } } }; enum moduleCode = q{ module api_entry; import std.stdio : writeln; import derelict.util.wintypes; export extern (C) { mixin(loadSystemSymbolsCode); } }; string getLoadSystemSymbolsCode(string bindinsCode)() { return loadSystemSymbolsCode.replace("%SYSTEM_BINDINGS%", bindinsCode); } string getModuleCode(string loadSystemSymbolsCode)() { return moduleCode.replace("%LOAD_SYSTEM_SYMBOLS%", loadSystemSymbolsCode); } void main() { import std.stdio : File; auto file = File("../opengl32/src/api_entry.d", "w"); file.writeln( getModuleCode!( getLoadSystemSymbolsCode!("test;")()) ); } Is there some materials for learning to do this kind of things with CTFE?
I feel my self little stupid, I don't need the " in the token string with the %WordToReplace%. So I think that the magic will happen.
Mar 16 2018