Re: Linking external functions?
DLearner via Digitalmars-d-learn wrote: On Tuesday, 18 April 2023 at 21:31:21 UTC, thinkunix wrote: [...] If not calling C code, why use extern(C) for D code? Wanted to test out options of calling D routine (possibly -betterC) from both C and (full) D. OK, thanks.
Re: Linking external functions?
On Tuesday, 18 April 2023 at 21:31:21 UTC, thinkunix wrote: [...] If not calling C code, why use extern(C) for D code? Wanted to test out options of calling D routine (possibly -betterC) from both C and (full) D.
Re: Linking external functions?
DLearner via Digitalmars-d-learn wrote: Wanted to try out linking two source files independantly compiled. ExtCallee.d source file: ``` extern(C) void ExtCallee() { import std.stdio; writeln("Entered: ", __FUNCTION__); writeln("Exiting: ", __FUNCTION__); } ``` ExtMain.d source file: ``` void main() { import std.stdio; extern(C) void ExtCallee(); writeln("Entered: ", __FUNCTION__); ExtCallee(); writeln("Exiting: ", __FUNCTION__); } What is the advantage of using extern(C)? Since both are D source files, why wouldn't you do just this: ```d // ExtCallee.d void ExtCallee() { import std.stdio; writeln("Entered: ", __FUNCTION__); writeln("Exiting: ", __FUNCTION__); } ``` ```d // ExtMain.d void main() { import std.stdio; import ExtCallee; writeln("Entered: ", __FUNCTION__); // I had to scope this to get it to compile // If instead I put the function in myfn.d and // did "import myfn;" it works without the scope operator. ExtCallee.ExtCallee(); writeln("Exiting: ", __FUNCTION__); } ``` Compile with: $ dmd ExtCallee.d ExtMain.d -of=prog Without extern(C), the linker mangles names: $ nm ExtCallee.o | grep ExtCallee R _D9ExtCallee12__ModuleInfoZ W _D9ExtCalleeQkFZv $ nm ExtMain.o | grep ExtCallee U _D9ExtCalleeQkFZv With extern(C), the linker does not mangle names: $ nm ExtCallee.o | grep ExtCallee W ExtCallee R _D9ExtCallee12__ModuleInfoZ $ nm ExtMain.o | grep ExtCallee U ExtCallee If not calling C code, why use extern(C) for D code? scot
Re: Linking external functions?
On Tuesday, 18 April 2023 at 20:05:05 UTC, DLearner wrote: Is the declaration inside main not visible to the linker? It affects the (fully qualified and mangled) name of the function. Compare: ```d extern(C) void ExtCallee(); pragma(msg, ExtCallee.mangleof); /* ExtCallee (correct name) */ void main() { extern(C) void ExtCallee(); pragma(msg, ExtCallee.mangleof); /* _D7ExtMain4mainFZ9ExtCalleeUZv (incorrect) */ } ``` I don't know the rationale behind that behavior, if there is one. Generally, just put your `extern(C)` prototypes in module scope.
Re: Linking external functions?
On Tuesday, 18 April 2023 at 20:00:18 UTC, ag0aep6g wrote: On Tuesday, 18 April 2023 at 19:49:04 UTC, DLearner wrote: ``` void main() { import std.stdio; extern(C) void ExtCallee(); ``` Move that declaration out of main. Thanks - worked! Is the declaration inside main not visible to the linker?
Re: Linking external functions?
On Tuesday, 18 April 2023 at 19:49:04 UTC, DLearner wrote: ``` void main() { import std.stdio; extern(C) void ExtCallee(); ``` Move that declaration out of main.
Re: Variable length arrays under -betterC?
On 4/17/23 11:34 AM, DLearner wrote: Requirement is to write some D code (which avoids the GC), that will be called from C. So simple approach seemed to be to write D code under -betterC restrictions. However, also need variable length arrays - but D Dynamic Arrays not allowed under -betterC. Any ideas how to implement variable length arrays under -betterC? variable-length arrays (i.e. slices) are valid in betterC. What isn't allowed is *GC-allocating* them and *appending* to them in betterC. ```d int[] arr; // fine // arr ~= 5; // nope, uses GC arr = (cast(int *)malloc(int.sizeof * 5))[0 .. 5]; // fine arr = arr[0 .. 3]; // also fine, no allocations needed arr = (cast(int*)realloc(arr.ptr, int.sizeof * 10))[0 .. 10]; // fine, but leaks the original pointer free(arr.ptr); // fine ``` What you *likely* want is an array type that handles some of the lifetime issues, or at least some UFCS/factory functions to make life easier (the above code is as bad as C code (except for the slicing)). But variable-length arrays work just fine as-is. As with any manual memory management system, you need to handle the lifetime more carefully and explicitly. There's a reason why reference counting is hard to implement. -Steve
Linking external functions?
Wanted to try out linking two source files independantly compiled. ExtCallee.d source file: ``` extern(C) void ExtCallee() { import std.stdio; writeln("Entered: ", __FUNCTION__); writeln("Exiting: ", __FUNCTION__); } ``` ExtMain.d source file: ``` void main() { import std.stdio; extern(C) void ExtCallee(); writeln("Entered: ", __FUNCTION__); ExtCallee(); writeln("Exiting: ", __FUNCTION__); } ``` Then: ``` dmd ExtCallee -c ``` which worked, producing .obj file. However: ``` dmd ExtCallee.obj -run ExtMain lld-link: error: undefined symbol: __D7ExtMain4mainFZ9ExtCalleeUZv referenced by ExtMain.obj:(__Dmain) Error: linker exited with status 1 ``` Ideas?
Re: Logging logs in Windows
On Tuesday, 18 April 2023 at 12:08:35 UTC, Richard (Rikki) Andrew Cattermole wrote: Sounds like a simple case of not linking against the right library: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-reporteventa Library Advapi32.lib DLL Advapi32.dll Should be as simple as adding advapi32 to your libs directive. Yes, you were right, it helped. [I will know that there is a footnote at the bottom with a description](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-reporteventa#requirements)
Re: Logging logs in Windows
On Saturday, 4 February 2023 at 14:48:55 UTC, Richard (Rikki) Andrew Cattermole wrote: I.e. here are my functions for syslog and Windows Event log (I won't copy it all, it won't be helpful & the file log function is giant compared). ```d void syslog() { version (Posix) { import core.sys.posix.syslog : syslog; syslog(prioritySyslogForLevels[level], unsafeTextMessageComposite.ptr); } } void windowsEvents() { version (Windows) { import core.sys.windows.windows : ReportEventA, WORD, DWORD, EVENTLOG_INFORMATION_TYPE, EVENTLOG_WARNING_TYPE, EVENTLOG_ERROR_TYPE; static WORD[] WTypes = [ EVENTLOG_INFORMATION_TYPE, EVENTLOG_INFORMATION_TYPE, EVENTLOG_WARNING_TYPE, EVENTLOG_ERROR_TYPE, EVENTLOG_ERROR_TYPE, EVENTLOG_ERROR_TYPE ]; static DWORD[] dwEventID = [0, 0, 0, 0, 0, 0]; const(char)*[2] messages = [ ModuleLine2.ptr, cast(char*)unsafeTextMessageComposite.ptr + unsafeDateTime.length + ModuleLine.length ]; ReportEventA(windowsEventHandle, WTypes[level], 0, dwEventID[level], cast(void*)null, 2, 0, &messages[0], cast(void*)null); } } ``` Note: you also need to setup an event source on Windows i.e. ```d import core.sys.windows.windows : RegisterEventSourceA; windowsEventHandle = RegisterEventSourceA(null, cast(char*)processName.ptr); ``` and to close it: ```d import core.sys.windows.windows : DeregisterEventSource; DeregisterEventSource(windowsEventHandle); ``` I tried to make a simple recording, but when compiling, he swears at linking. ```d import core.sys.windows.windows; void writeToEventLog(LPCSTR pszSrcName, LPCSTR message) { HANDLE hEventLog = RegisterEventSourceA(NULL, pszSrcName); ReportEventA(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL, 1, 0, &message, NULL); DeregisterEventSource(hEventLog); } void main() { writeToEventLog("test", "This is test message"); } ``` ```ps PS C:\sources\d-journals> dub Starting Performing "debug" build using C:\D\dmd2\windows\bin64\dmd.exe for x86_64. Building d-journals ~master: building configuration [application] Linking d-journals lld-link: error: undefined symbol: RegisterEventSourceA referenced by C:\sources\d-journals\source\app.d:4 C:\Users\alexander\AppData\Local\dub\cache\d-journals\~master\build\application-debug-windows-x86_64-dmd_v2.102.0-dirty-92393AAC9FC80DD3A486D7D072118EACA853FFECDE2EEAA8920EDA92F0620E60\d-journals.obj:(_D3app15writeToEventLogFPxaQdZv) lld-link: error: undefined symbol: ReportEventA referenced by C:\sources\d-journals\source\app.d:5 C:\Users\alexander\AppData\Local\dub\cache\d-journals\~master\build\application-debug-windows-x86_64-dmd_v2.102.0-dirty-92393AAC9FC80DD3A486D7D072118EACA853FFECDE2EEAA8920EDA92F0620E60\d-journals.obj:(_D3app15writeToEventLogFPxaQdZv) lld-link: error: undefined symbol: DeregisterEventSource referenced by C:\sources\d-journals\source\app.d:6 C:\Users\alexander\AppData\Local\dub\cache\d-journals\~master\build\application-debug-windows-x86_64-dmd_v2.102.0-dirty-92393AAC9FC80DD3A486D7D072118EACA853FFECDE2EEAA8920EDA92F0620E60\d-journals.obj:(_D3app15writeToEventLogFPxaQdZv) Error: linker exited with status 1 Error C:\D\dmd2\windows\bin64\dmd.exe failed with exit code 1. ``` What could I have missed?
Re: Logging logs in Windows
Sounds like a simple case of not linking against the right library: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-reporteventa Library Advapi32.lib DLL Advapi32.dll Should be as simple as adding advapi32 to your libs directive.
Re: Variable length arrays under -betterC?
On Tuesday, 18 April 2023 at 06:20:43 UTC, Richard (Rikki) Andrew Cattermole wrote: On 18/04/2023 1:33 PM, Salih Dincer wrote: I understand from the thread this: D gives us -betterC but nothing from the Phobos. So he says, see what you have, do what the hell you want! Am I wrong about this? Nope. -betterC means you have no runtime or standard library support. You are very much on your own. With betterC, some Phobos functionality work. For instance, most of std.range and std.algorithm will work. Problem is that there is no list of those in the docs. If something does GC allocations (std.container) or throws exceptions, it will not work. Based on my experience, -betterC, as its name implies, still provides a good programming experience rather than C.
Re: short guide on getting started with D
On Monday, 3 April 2023 at 07:29:01 UTC, cgenie wrote: Hello, I created a short guide on getting started with D: https://blog.mmksoft.uk/#A%20short%20guide%20on%20getting%20started%20with%20D%20programming This is because I recently I started to explore the language and, having read the forum, I see DUB being discouraged quite often. I would appreciate any remarks. Best, Przemek Sorry for the very late reply. I've been thinking on commenting on this but I'm lazy. You're saying you don't want to use DUB? In that case, I think you should not add it to your dependencies at all. DUB is both a package manager and a build tool, but here Nix is answering for the package management and Meson is your build system. Have Meson to use LDC directly instead. Since you're using Nix, in case you change your mind about DUB (maybe to build a third-party package), it needs to be said that using it isn't straightforward since Nix won't let DUB download the dependencies from the Internet on it's own. There's a solution, though: [dub2nix](https://github.com/lionello/dub2nix). If you're interested, watch it's authors [DConf talk](https://dconf.org/2019/talks/lunesu.html) for more info. Anyway, there are not many examples about using D with Nix. Your post is addressing that, so thanks for writing it up.