NO

Author Topic: Calling a function from DLL at runtime  (Read 1346 times)

Offline John Z

  • Member
  • *
  • Posts: 796
Re: Calling a function from DLL at runtime
« Reply #15 on: October 07, 2023, 12:08:36 PM »

This will get you there.  This is the A version. 
If you want the W versions, it's only minor edits.


Thanks!  This works very well, both modal and non-modal.  Adding it to my 'Utilities.c' file.  :)

John Z

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Calling a function from DLL at runtime
« Reply #16 on: October 07, 2023, 12:33:39 PM »
Adding it to my 'Utilities.c' file.  :)
Simple Tip:
If you have many 'utility' functions/procedures is better to create a static library project and put each related group of functions in a single separated file (C module). Then using the library you will link to the executable only the functions/procedures used, producing a smaller executable.
If all utility functions/procedures are coded in a single file (C module) probably the linker will put all of them, used and unused, in the executable producing a larger file.  ;)
« Last Edit: October 07, 2023, 12:35:11 PM by frankie »
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

Online Vortex

  • Member
  • *
  • Posts: 802
    • http://www.vortex.masmcode.com
Re: Calling a function from DLL at runtime
« Reply #17 on: October 07, 2023, 07:57:11 PM »
Frankie is right. It'a about the granularity concept. From Microsoft Macro Assembler's Programmer's Guide :

Quote
Granularity : The degree to which library procedures can be linked as individual blocks of code. In
Microsoft libraries, granularity is at the object-file level. If a single object file containing three
procedures is added to a library, all three procedures will be linked with the main program even if only
one of them is actually called.
Code it... That's all...

Offline jcfuller

  • Member
  • *
  • Posts: 36
Re: Calling a function from DLL at runtime
« Reply #18 on: October 08, 2023, 11:37:44 AM »
I don't code much anymore and my memory is a bit faulty these days but I used this with VC++.
https://learn.microsoft.com/en-us/cpp/build/reference/gy-enable-function-level-linking?view=msvc-170

James

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2091
Re: Calling a function from DLL at runtime
« Reply #19 on: October 08, 2023, 02:34:31 PM »
I don't code much anymore and my memory is a bit faulty these days but I used this with VC++.
https://learn.microsoft.com/en-us/cpp/build/reference/gy-enable-function-level-linking?view=msvc-170

James
since ml version 12 ( msvc 2013 ) is commandline option /Gy[-] separate functions for linker
so it support COMDAT
« Last Edit: October 08, 2023, 03:04:46 PM by TimoVJL »
May the source be with you

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2266
    • http://www.smorgasbordet.com
Re: Calling a function from DLL at runtime
« Reply #20 on: October 08, 2023, 02:52:40 PM »
I don't code much anymore and my memory is a bit faulty these days but I used this with VC++.
https://learn.microsoft.com/en-us/cpp/build/reference/gy-enable-function-level-linking?view=msvc-170
I looked at this a long time ago, and may have forgotten some things, but IIRC the problem for me was that the COFF file format didn't really support this. It had to be implemented using somewhat fuzzy conventions.

An example: the C runtime is split up into individual files since this worked best a long time ago, when compilers/computers were slower and a MAKEFILE made sure the least amount of rebuilding were done. For me, mentally, I still like this split: one task per source file. One thing to focus on, even if the solution requires multiple functions to implement. Maybe it's just me...
/Pelle

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Calling a function from DLL at runtime
« Reply #21 on: October 08, 2023, 03:52:37 PM »
Compilers use different approach to separate functions independently from the module they belong.
The GCC suite makes available the flag -ffunction-sections which splits the functions code in different segments in ELF format. For each function is created a subsection prepended by a period with the function name. I.e. for function:
Code: [Select]
int foo
{
    return 42;
}
Will be coded as a .text subsegment .text.foo:
Code: [Select]
Section Headers:
  [Nr] Name          Type      Addr  Off  Size ES Flg Lk Inf Al
  [ 0]               NULL      00000 0000 0000 00      0   0  0
  [ 1] .text         PROGBITS  00000 0034 0000 00  AX  0   0  1
  [ 2] .data         PROGBITS  00000 0034 0000 00  WA  0   0  1
  [ 3] .bss          NOBITS    00000 0034 0000 00  WA  0   0  1
  [ 4] .text.foo     PROGBITS  00000 0034 001c 00  AX  0   0  4
  [..]
This technique allows to easily merge all text sections back in the single text sections by having *(.text.*) spec along with *(.text) spec in built-in linker scripts.
Anyway a similar facility, named Grouped Sections, is available in MS-COFF format (available only in OBJ files), currently used for the debug sections in PellesC, where the separator used is the '$' sign:
Code: [Select]
Dump of EnumSymbols.obj
File type: OBJ
SUMMARY
      20 .data
    104B .debug$S
     3AC .debug$T
      51 .drectve
      18 .pdata
    1444 .rdata
     14A .text
      18 .xdata

MS defines Grouped sections as:
Quote
Grouped Sections (Object Only)

The "$" character (dollar sign) has a special interpretation in section names in object files.
When determining the image section that will contain the contents of an object section, the linker discards the "$" and all characters that follow it. Thus, an object section named .text$X actually contributes to the .text section in the image.
However, the characters following the "$" determine the ordering of the contributions to the image section. All contributions with the same object-section name are allocated contiguously in the image, and the blocks of contributions are sorted in lexical order by object-section name. Therefore, everything in object files with section name .text$X ends up together, after the .text$W contributions and before the .text$Y contributions.
The section name in an image file never contains a "$" character.
In analogy to the ELF format we can imagine something like:
Code: [Select]
Dump of foo.obj
File type: OBJ
SUMMARY
      20 .data
    104B .debug$S
     3AC .debug$T
      51 .drectve
      18 .pdata
    1444 .rdata
     14A .text
     15A .text.foo
      18 .xdata

Of course considering this possible doesn't mean that the implementation is easy...  :(
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

Offline John Z

  • Member
  • *
  • Posts: 796
Re: Calling a function from DLL at runtime
« Reply #22 on: October 08, 2023, 04:02:26 PM »
For me, mentally, I still like this split: one task per source file. One thing to focus on, even if the solution requires multiple functions to implement. Maybe it's just me...

That is what I try to maintain as well for any relatively large program.  One 'major' task per source file.  For Example if BASE64 conversions are needed then one source file for that, or export to ODS - one file.  However it makes sense that one other source file contains small routines that are used in several major task source files.  For example a character replacement routine or a left trim that is used in multiple other sources.

I didn't think about what happens with a routine being included that was written but never called....

John Z

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2266
    • http://www.smorgasbordet.com
Re: Calling a function from DLL at runtime
« Reply #23 on: October 08, 2023, 05:42:22 PM »
Of course considering this possible doesn't mean that the implementation is easy...  :(
Technically not hard, but there are other problems:
- how should this interact with the #pragma's code_seg, data_seg, and const_seg (I really don't know).
- many functions contain literal strings and/or static data, that will not be covered by this (referenced strings and most data are emitted at the end of the compilation, when associated function context is long lost; the data will be included by the linker, but then never referenced)
/Pelle

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2266
    • http://www.smorgasbordet.com
Re: Calling a function from DLL at runtime
« Reply #24 on: October 08, 2023, 05:48:59 PM »
However it makes sense that one other source file contains small routines that are used in several major task source files.  For example a character replacement routine or a left trim that is used in multiple other sources.
There are always multiple ways of doing things.

I have put all my truly general functions, the ones that span multiple projects, into a separate static library (and yes, each function in a separate source file). Linking with this library will pull in just what's needed.

Functions that are general for a single project (only), tend to be used in my experience (so not really a problem).
/Pelle

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Calling a function from DLL at runtime
« Reply #25 on: October 08, 2023, 07:03:42 PM »
- how should this interact with the #pragma's code_seg, data_seg, and const_seg (I really don't know).
Well, the section flags in the Characteristics field of a section header defines the properties of the segment, executable, read-only, etc. This could help to classify it in a specific type: code, uninitialized data, read-only data, etc. This during the link identify the final standard MS-COFF segments (full list).
When the pragma segment name is defined we have 2 options: still use the section grouping (i.e. <code_section_name>$<function_name>), or simply ignore it.

- many functions contain literal strings and/or static data, that will not be covered by this (referenced strings and most data are emitted at the end of the compilation, when associated function context is long lost; the data will be included by the linker, but then never referenced)
A solution could be to create a grouped data section also for collateral segments in the form <data_section_name>$<function_name>. This should help to determine if the segment should be included or not in the link.

Not easy, I confirm my assertion  :(, but IMO the real point is: is it worth of? If you really want to implement the MS switch /Gy then yes. Else I don't know.

What I think can be really useful is to respect the alphabetic order of the grouped sections during the code emission, because could be helpful to the sequence positioning of data in the file.
« Last Edit: October 08, 2023, 08:09:43 PM by frankie »
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2266
    • http://www.smorgasbordet.com
Re: Calling a function from DLL at runtime
« Reply #26 on: October 08, 2023, 08:33:59 PM »
but IMO the real point is: is it worth of?
I don't think so, since there are easy ways around it, but the question comes up once in a while ("since the big compilers can do it, why can't you?" yada, yada, yada...)

In some ways, a better idea would be to implement link-time optimization, but:
1) this makes much more sense for a language like C++, which will almost by definition produce many small functions (some likely identical at the machine code level), or when you build something huge like Word or Firefox.
2) this is a massive amount of work, and since C isn't C++ (yet), it's never going to happen (with Pelles C).

What I think can be really useful is to respect the alphabetic order of the grouped sections during the code emission, because could be helpful to the sequence positioning of data in the file.
If we talk about the same thing, the '$' grouping stuff requires sorting. This is (among other things) how various C runtimes collect data-blocks from different object files; use f.e. .somename$XA as the starting placeholder, .somename$XZ and the ending placeholder, and .somename$X<whatever> in different object files. When running, any data will be packed between .somename$XA and .somename$XZ (disregarding alignment, etc).

/Pelle

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2096
Re: Calling a function from DLL at runtime
« Reply #27 on: October 08, 2023, 09:01:24 PM »
but IMO the real point is: is it worth of?
I don't think so, since there are easy ways around it, but the question comes up once in a while ("since the big compilers can do it, why can't you?" yada, yada, yada...)
I agree, it is very important when compiling for small memory systems, as embedded programming where the ffunction-sections switch is mandatory to keep low the memory footprint, and on very large compile jobs (C++ and other object oriented languages or large programs).
With careful structuring of source modules there should be no big problems.

What I think can be really useful is to respect the alphabetic order of the grouped sections during the code emission, because could be helpful to the sequence positioning of data in the file.
If we talk about the same thing, the '$' grouping stuff requires sorting. This is (among other things) how various C runtimes collect data-blocks from different object files; use f.e. .somename$XA as the starting placeholder, .somename$XZ and the ending placeholder, and .somename$X<whatever> in different object files. When running, any data will be packed between .somename$XA and .somename$XZ (disregarding alignment, etc).
Yes. I meant exactly that, and for that scope.  :)
« Last Edit: October 08, 2023, 09:05:58 PM by frankie »
It is better to be hated for what you are than to be loved for what you are not. - Andre Gide

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2266
    • http://www.smorgasbordet.com
Re: Calling a function from DLL at runtime
« Reply #28 on: October 08, 2023, 09:21:50 PM »
Yes. I meant exactly that, and for that scope.  :)
OK, good. I think this sorting have been in my linker since version 1.0, before much of it was documented. Internally it's just "the weird dollar rule", but it was essential when linking objects and libraries from Microsoft (I can't remember exactly what broke without this "feature").
/Pelle