Re: [OT] #define

2017-05-23 Thread Andrew Edwards via Digitalmars-d-learn

On Tuesday, 23 May 2017 at 00:14:43 UTC, Mike Parker wrote:

On Monday, 22 May 2017 at 18:44:10 UTC, Andrew Edwards wrote:


There isn't any Windows specific section. Every function 
pointer in the library is decorated in one of the following 
two forms


void (APIENTRY *NAME)(PARAMS)

or

void (APIENTRYP NAME)(PARAMS)


Sorry, I worded that poorly. APIENTRY is defined somewhere in 
the Win32 headers. IIRC, it's an alias for WINAPI, which is 
also defined in the Win32 headers to declare the standard call 
calling convention (which is __stdcall on the MS compiler and 
something else, I think, on GCC). OpenGL includes windows.h on 
Windows, so the Win32-specific stuff is there. The functions 
aren't in any Win32-specific sections.




[]

Much appreciated Mike and everyone else. I was able to make a 
good deal of progress today because of your input.


Andrew


Re: [OT] #define

2017-05-22 Thread Andrew Edwards via Digitalmars-d-learn

On Monday, 22 May 2017 at 18:48:44 UTC, Adam D. Ruppe wrote:

On Monday, 22 May 2017 at 18:44:10 UTC, Andrew Edwards wrote:
Both happen to be the exact same. So does mean that for every 
function pointer in the file, I need to duplicate as such?


You can use `extern(System)` or that case in D.

It will be extern(Windows) on win an extern(C) elsewhere - just 
like what the C is doing.


Okay... got it. Thanks.


Re: [OT] #define

2017-05-22 Thread Mike Parker via Digitalmars-d-learn

On Monday, 22 May 2017 at 18:44:10 UTC, Andrew Edwards wrote:


There isn't any Windows specific section. Every function 
pointer in the library is decorated in one of the following two 
forms


void (APIENTRY *NAME)(PARAMS)

or

void (APIENTRYP NAME)(PARAMS)


Sorry, I worded that poorly. APIENTRY is defined somewhere in the 
Win32 headers. IIRC, it's an alias for WINAPI, which is also 
defined in the Win32 headers to declare the standard call calling 
convention (which is __stdcall on the MS compiler and something 
else, I think, on GCC). OpenGL includes windows.h on Windows, so 
the Win32-specific stuff is there. The functions aren't in any 
Win32-specific sections.





Both happen to be the exact same. So does mean that for every 
function pointer in the file, I need to duplicate as such?


version (Windows)
{
extern(Windows)
{
alias NAME = void function(PARAMS);
}
}
else
{
extern(C)
{
alias NAME = void function(PARAMS);
}
}


Adam's answer about extern(System) is the solution. Before it was 
added, this code is exactly what I had to use in Derelict.





So if I'm understanding correctly, on Windows platforms this:

typedef void (APIENTRYP PFNGLDISABLEPROC)(GLenum cap);
GLAPI PFNGLDISABLEPROC glad_glDisable;
#define glDisable glad_glDisable

is technically:

typedef void (__syscall* PFNGLDISABLEPROC)(GLenum cap);
extern "C" PFNGLDISABLEPROC glad_glDisable;
#define glDisable glad_glDisable


__stdcall, not __syscall


which in D is:

// extern (Windows) obviated by the fact that the following 
line exports to the C API?

extern (C) alias glad_glDisable = void function(GLenum cap);
glad_glDisable glDisable;



extern(System) for anything cross-platform. If it's something 
you're using only on Windows, then you can use extern(Windows).





Re: [OT] #define

2017-05-22 Thread Adam D. Ruppe via Digitalmars-d-learn

On Monday, 22 May 2017 at 18:44:10 UTC, Andrew Edwards wrote:
Both happen to be the exact same. So does mean that for every 
function pointer in the file, I need to duplicate as such?


You can use `extern(System)` or that case in D.

It will be extern(Windows) on win an extern(C) elsewhere - just 
like what the C is doing.





Re: [OT] #define

2017-05-22 Thread Andrew Edwards via Digitalmars-d-learn

On Monday, 22 May 2017 at 16:56:10 UTC, Mike Parker wrote:

On Monday, 22 May 2017 at 16:37:51 UTC, Andrew Edwards wrote:


Specific context at the following links:




https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L24-L48


Generally, any functions in the Windows-specific sections with 
APIENTRY in their declarations need to be declared in D as 
extern(Windows). APIENTRY itself can be left out of the D 
binding.




There isn't any Windows specific section. Every function pointer 
in the library is decorated in one of the following two forms


void (APIENTRY *NAME)(PARAMS)

or

void (APIENTRYP NAME)(PARAMS)

Both happen to be the exact same. So does mean that for every 
function pointer in the file, I need to duplicate as such?


version (Windows)
{
extern(Windows)
{
alias NAME = void function(PARAMS);
}
}
else
{
extern(C)
{
alias NAME = void function(PARAMS);
}
}


https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L57-L81



Again, GLAPI is a Windows-specific thing. [...]

You can safely ignore this one, unless you're planning to do a 
pure D port (not binding) of the library and intend to compile 
as a shared lib. It tells you which functions need to be 
exported from the shared lib to match the C API.


So if I'm understanding correctly, on Windows platforms this:

typedef void (APIENTRYP PFNGLDISABLEPROC)(GLenum cap);
GLAPI PFNGLDISABLEPROC glad_glDisable;
#define glDisable glad_glDisable

is technically:

typedef void (__syscall* PFNGLDISABLEPROC)(GLenum cap);
extern "C" PFNGLDISABLEPROC glad_glDisable;
#define glDisable glad_glDisable

which in D is:

// extern (Windows) obviated by the fact that the following 
line exports to the C API?

extern (C) alias glad_glDisable = void function(GLenum cap);
glad_glDisable glDisable;


https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L88-L124

[...]
This one can also be ignored on the D side.


Got it.



Re: [OT] #define

2017-05-22 Thread Mike Parker via Digitalmars-d-learn

On Monday, 22 May 2017 at 16:37:51 UTC, Andrew Edwards wrote:


Specific context at the following links:




https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L24-L48


APIENTRY is typically defined in Windows headers to set the 
stdcall calling convention (which is where we get extern(Windows) 
in D) in function declarations. You'll find it all over Win32 API 
headers. In this case, since OpenGL uses it on Windows, glad is 
checking if it's defined and, if not, defining it as empty for 
non-Windows platforms. That way it can be used in the function 
signatures glad generates on every platform.


Generally, any functions in the Windows-specific sections with 
APIENTRY in their declarations need to be declared in D as 
extern(Windows). APIENTRY itself can be left out of the D binding.




https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L57-L81



Again, GLAPI is a Windows-specific thing. A lot of libraries that 
support compiling to a DLL define something similar on Windows. 
Function declarations need to be exported when compiling a DLL 
and imported when compiling programs that use the DLL, so the 
FOOAPI technique is used to apply the correct attribute to each 
declaration. On other platforms, FOOAPI is defined as empty.


You can safely ignore this one, unless you're planning to do a 
pure D port (not binding) of the library and intend to compile as 
a shared lib. It tells you which functions need to be exported 
from the shared lib to match the C API.



https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L88-L124


This one is a guard that makes sure that everything in the 
#ifndef GLEXT_64_TYPES_DEFINED block is only imported once. It's 
explained in the comment:


/* This code block is duplicated in glxext.h, so must be 
protected */


By defining GLEXT_64_TYPES_DEFINED, if glxext.h after, then it 
presumably also has a #ifndef GLEXT_64_TYPES_DEFINED block and 
will not redefine those types.


This one can also be ignored on the D side.




Re: [OT] #define

2017-05-22 Thread Andrew Edwards via Digitalmars-d-learn

On Monday, 22 May 2017 at 13:52:35 UTC, Dukc wrote:

On Monday, 22 May 2017 at 13:11:15 UTC, Andrew Edwards wrote:
Sorry if this is a stupid question but it eludes me. In the 
following, what is THING? What is SOME_THING?

[...]

I assume you know that the above part is c/c++ preprocessor, 
which is not normally used at d?


Yes, I am aware.

THING is nothing there. If you use it at code, I'm not sure how 
it behaves. Either it does not compile at all, or it behaves as 
nothing (think whitespace). If it's the latter, SOME_THING 
would be a lone asterix. Can be used as operator both unarily 
and binarily. #IFNDEF regonizes all preprocessor declarations, 
empty or not.


The closest D equivalent to #DEFINE is a string mixin. The 
equivalent to above is:

static if (!is(typeof(thing))) enum thing = "";
static if (!is(typeof(someThing))) enum someThing = thing ~ " 
*";

[...]

...you have to explicitly mix the text in:

@safe void main()
{   import std.stdio;
mixin("writeln(5 " ~ someThing ~ " 6);"); //30
}


That's really ugly... Hope I'll never have to resort to that. The 
specific idiom does have it's uses though, as in the case of 
self-important lookups.



[...]

-If the symbol is an empty declaration used only for #IFNDEFS, 
version statements are a cood canditate for replacing it. 
Perhaps that's what you're looking for?


Not exactly but I get the point. This list is golden, thanks for 
the assist.


Andrew



Re: [OT] #define

2017-05-22 Thread Andrew Edwards via Digitalmars-d-learn

On Monday, 22 May 2017 at 13:15:31 UTC, Adam D. Ruppe wrote:

On Monday, 22 May 2017 at 13:11:15 UTC, Andrew Edwards wrote:

#ifndef THING
#define THING
#endif


This kind of thing is most commonly used in include guards

https://en.wikipedia.org/wiki/Include_guard#Use_of_.23include_guards


Have a basic understanding. In the specific case i'm looking at, 
they are not used as include guards though.


You can usually just strip that out in D, since the module 
system already just works if imported twice.


Makes sense.


#ifndef SOME_THING
#define SOME_THING THING *
#endif

Is this equivalent to:

alias thing = void;
alias someThing = thing*;


I'd have to see that in context though to see why they are 
doing it... it is probably some kind of platform specific type 
definitions.


Specific context at the following links:

https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L24-L48

https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L57-L81

https://github.com/glfw/glfw/blob/66ff4aae89572419bb130c5613798e34d7521fc7/deps/glad/glad.h#L88-L124

Thanks,
Andrew


Re: [OT] #define

2017-05-22 Thread Andrew Edwards via Digitalmars-d-learn

On Monday, 22 May 2017 at 13:18:51 UTC, Eugene Wissner wrote:

On Monday, 22 May 2017 at 13:11:15 UTC, Andrew Edwards wrote:
Sorry if this is a stupid question but it eludes me. In the 
following, what is THING? What is SOME_THING?


#ifndef THING
#define THING
#endif

#ifndef SOME_THING
#define SOME_THING THING *
#endif

Is this equivalent to:

alias thing = void;
alias someThing = thing*;

Thanks,
Andrew


No, it isn't. THING is empty. Some SOME_THING is "*".

Emtpy macros are used for example to inline the functions:

#ifndef MY_INLINE
#define MY_INLINE
#endif

MY_INLINE void function()
{
}

So you can choose at compile time if you want inline the 
function or not. D is here more restrictive than C, I don't 
know a way to port to D.


Thanks Eugene, got it. For context, see response to Adam.


Re: [OT] #define

2017-05-22 Thread biocyberman via Digitalmars-d-learn

On Monday, 22 May 2017 at 13:11:15 UTC, Andrew Edwards wrote:
Sorry if this is a stupid question but it eludes me. In the 
following, what is THING? What is SOME_THING?


#ifndef THING
#define THING
#endif

#ifndef SOME_THING
#define SOME_THING THING *
#endif

Is this equivalent to:

alias thing = void;
alias someThing = thing*;

Thanks,
Andrew


Hi Andrew
This is why need to learn more about C and C++ when I want to 
port them to D. You can get a bit of reading about C preprocessor 
here: 
https://www.tutorialspoint.com/cprogramming/c_preprocessors.htm


Regarding your question: I've been porting some C code with 
macros, they can be translated into D as aliases, functions, 
structs, templates, mixins etc. So maybe an excerpt from the real 
code would be more straight forward.


Re: [OT] #define

2017-05-22 Thread Dukc via Digitalmars-d-learn

On Monday, 22 May 2017 at 13:11:15 UTC, Andrew Edwards wrote:
Sorry if this is a stupid question but it eludes me. In the 
following, what is THING? What is SOME_THING?


#ifndef THING
#define THING
#endif

#ifndef SOME_THING
#define SOME_THING THING *
#endif

Is this equivalent to:

alias thing = void;
alias someThing = thing*;

Thanks,
Andrew


I assume you know that the above part is c/c++ preprocessor, 
which is not normally used at d?


THING is nothing there. If you use it at code, I'm not sure how 
it behaves. Either it does not compile at all, or it behaves as 
nothing (think whitespace). If it's the latter, SOME_THING would 
be a lone asterix. Can be used as operator both unarily and 
binarily. #IFNDEF regonizes all preprocessor declarations, empty 
or not.


The closest D equivalent to #DEFINE is a string mixin. The 
equivalent to above is:

static if (!is(typeof(thing))) enum thing = "";
static if (!is(typeof(someThing))) enum someThing = thing ~ " *";

This is used differently than a preprocessor though. Instead of:

@safe void main()
{   import std.stdio;
writeln(5 SOMETHING 6);
}

...you have to explicitly mix the text in:

@safe void main()
{   import std.stdio;
mixin("writeln(5 " ~ someThing ~ " 6);"); //30
}

Because just mixing in text straight away is generally quite an 
ugly solution, so is the syntax. In most cases you would want to 
replace it with a more context-specific solution:


-If the symbol is a literal, an enum literal OF THE TYPE OF THE 
LITERAL is preferred.


-If the symbol is an empty declaration used only for #IFNDEFS, 
version statements are a cood canditate for replacing it. Perhaps 
that's what you're looking for?


-If the symbol is a type, or a name of another global symbol, 
alias is the way to go.


-In the case of function-type #DEFINES, eponymous templates or 
aliases to lambdas are your best bets.


Note, there is no equivalent to #UNDEF in D. But unlike the 
preprocessor, all D symbols cease to exist when their scope ends, 
and in almost all cases that's a much better thing!


Re: [OT] #define

2017-05-22 Thread Eugene Wissner via Digitalmars-d-learn

On Monday, 22 May 2017 at 13:11:15 UTC, Andrew Edwards wrote:
Sorry if this is a stupid question but it eludes me. In the 
following, what is THING? What is SOME_THING?


#ifndef THING
#define THING
#endif

#ifndef SOME_THING
#define SOME_THING THING *
#endif

Is this equivalent to:

alias thing = void;
alias someThing = thing*;

Thanks,
Andrew


No, it isn't. THING is empty. Some SOME_THING is "*".

Emtpy macros are used for example to inline the functions:

#ifndef MY_INLINE
#define MY_INLINE
#endif

MY_INLINE void function()
{
}

So you can choose at compile time if you want inline the function 
or not. D is here more restrictive than C, I don't know a way to 
port to D.


Re: [OT] #define

2017-05-22 Thread Adam D. Ruppe via Digitalmars-d-learn

On Monday, 22 May 2017 at 13:11:15 UTC, Andrew Edwards wrote:

#ifndef THING
#define THING
#endif


This kind of thing is most commonly used in include guards

https://en.wikipedia.org/wiki/Include_guard#Use_of_.23include_guards

You can usually just strip that out in D, since the module system 
already just works if imported twice.



#ifndef SOME_THING
#define SOME_THING THING *
#endif

Is this equivalent to:

alias thing = void;
alias someThing = thing*;


I'd have to see that in context though to see why they are doing 
it... it is probably some kind of platform specific type 
definitions.