Jump to page: 1 2 3
Thread overview
Cannot check function address
May 24, 2022
frame
May 24, 2022
frame
May 24, 2022
Alain De Vos
May 24, 2022
Adam D Ruppe
May 25, 2022
frame
May 25, 2022
frame
May 25, 2022
frame
May 25, 2022
frame
May 25, 2022
frame
May 25, 2022
frame
May 25, 2022
user1234
May 25, 2022
frame
May 24, 2022
Adam Ruppe
May 24, 2022

I have a function slot that may be loaded via a shared library.
I want to check if that function has an address but compiler (DMD 2.100, Windows) instead tries to invocate the function?

// --- module a:
alias F = extern (C) void function(string param);
F fun = someLibLoad!F("name");

assert(fun !is null); // compiles (also works in runtime)

// --- module b:
import a;

// same code:
//
// error: missing argument for parameter #1: ... with 2.098.1 or
// error: too few arguments, expected `5`, got `0` ... with 2.100
assert(fun !is null);

Usually that works fine as shown in module A but for some reason not in module B.
Workaround ideas? I tried casting to void* or ptrdiff_t but the compiler always tries to call the function -.-

May 24, 2022

On 5/24/22 2:54 PM, frame wrote:

>

I have a function slot that may be loaded via a shared library.
I want to check if that function has an address but compiler (DMD 2.100, Windows) instead tries to invocate the function?

// --- module a:
alias F = extern (C) void function(string param);
F fun = someLibLoad!F("name");

assert(fun !is null); // compiles (also works in runtime)

This doesn't seem valid for module-level code, assert is an instruction, not a declaration.

>

// --- module b:
import a;

// same code:
//
// error: missing argument for parameter #1: ... with 2.098.1 or
// error: too few arguments, expected 5, got 0 ... with 2.100
assert(fun !is null);


Usually that works fine as shown in module A but for some reason not in module B.
Workaround ideas? I tried casting to void* or ptrdiff_t but the compiler always tries to call the function -.-

expected 5 got 0 suggests it is finding some other fun, as a.fun only takes a single parameter.

Try std.traits.fullyQualifiedName!fun to see where it's coming from.

-Steve

May 24, 2022

On 5/24/22 3:09 PM, Steven Schveighoffer wrote:

>

assert is an instruction, not a declaration.

errr.... it's a statement, not a declaration.

-Steve

May 24, 2022

On Tuesday, 24 May 2022 at 18:54:33 UTC, frame wrote:

>

Usually that works fine as shown in module A but for some reason not in module B.

Do you have some other definition of fun somewhere?

May 24, 2022

On Tuesday, 24 May 2022 at 19:09:52 UTC, Steven Schveighoffer wrote:

>

This doesn't seem valid for module-level code, assert is an instruction, not a declaration.
...
Try std.traits.fullyQualifiedName!fun to see where it's coming from.

expected 5 got 0 suggests it is finding some other fun, as a.fun only takes a single parameter.

Of course this assert() is actually inside static this() and there is only one declaration. I just want to show that the used symbol and call is the same.

Also this is working code. I just put the assert() there to ensure the function isn't called by a race condition before it was loaded (module constructors often have cyclic dependency, so I cannot put this in a more clean way).

Those asserts() are set in:

module A: module constructor
module B: some function

To also anwser to Adam: no, this symbol is unique. The first line of the error says:

Error: function `a.fun(string param)` is not callable using argument types `()`.

Note that I have changed the actual module name and signature, it has orginal 5 arguments and very long names.

The point is, it shouldn't be called in this line anyway?

May 24, 2022

Just looking at the error, are 2.098.1 & 2.100 , 100% compatible ?

May 24, 2022
On Tuesday, 24 May 2022 at 22:10:21 UTC, frame wrote:
> To also anwser to Adam: no, this symbol is unique. The first line of the error says:
>
> ```
> Error: function `a.fun(string param)` is not callable using argument types `()`.
> ```

There's a big difference between a function and a function pointer.

This error message says "function". But the code you showed as a function pointer.

If it were a function pointer, the error would be:

```
Error: function pointer `a()` is not callable using argument types
(int)`
```


So there is clearly some kind of mix up here.

> The point is, it shouldn't be called in this line anyway?

If it is a function, you get its address with the & operator. But if it is supposed to be a function pointer, something is wrong with the declaration...
May 24, 2022

On 5/24/22 6:10 PM, frame wrote:

>

On Tuesday, 24 May 2022 at 19:09:52 UTC, Steven Schveighoffer wrote:

>

This doesn't seem valid for module-level code, assert is an instruction, not a declaration.
...
Try std.traits.fullyQualifiedName!fun to see where it's coming from.

expected 5 got 0 suggests it is finding some other fun, as a.fun only takes a single parameter.

Of course this assert() is actually inside static this() and there is only one declaration. I just want to show that the used symbol and call is the same.

"of course" I have no idea what your real code looks like, unless you post the real code.

While I get the point of trying to slim down the example to something postable, a very common problem with this kind of self-trimming is that you end up trimming out the problematic code. Why? Because if you noticed the problematic code, you wouldn't be posting here, you would just fix it. This, in fact, happens to me frequently.

Now, it's also possible that there is an actual compiler bug here, it certainly seems like it could be, but a full (non-)working example would be useful.

I still highly recommend trying code like:

import std.traits;
pragma(msg, fullyQualifiedName!fun);

inside the place where your assert is failing. To me, if it's using the expected symbol for fun (or whatever it's called), then it should print the definition you expect from the module you expect. If not, maybe there is a name conflict, and it's picking the wrong one? These problems can be tricky to find.

-Steve

May 25, 2022

On Wednesday, 25 May 2022 at 01:23:56 UTC, Steven Schveighoffer wrote:

>

"of course" I have no idea what your real code looks like, unless you post the real code.

While I get the point of trying to slim down the example to something postable, a very common problem with this kind of self-trimming is that you end up trimming out the problematic code. Why? Because if you noticed the problematic code, you wouldn't be posting here, you would just fix it. This, in fact, happens to me frequently.

Now, it's also possible that there is an actual compiler bug here, it certainly seems like it could be, but a full (non-)working example would be useful.

I still highly recommend trying code like:

import std.traits;
pragma(msg, fullyQualifiedName!fun);

inside the place where your assert is failing. To me, if it's using the expected symbol for fun (or whatever it's called), then it should print the definition you expect from the module you expect. If not, maybe there is a name conflict, and it's picking the wrong one? These problems can be tricky to find.

-Steve

Sorry, this was not affront, it was meant as my POV that you may have problems to get my problem because I have (as usually) forgot to make this more visible that some code was truncated.

I tried your suggestion, as replied to Adam - the symbol is unique and it shows that correct location. It's not different from the error message.

However, this error has nothing to do with assert(). In fact the compiler allows nothing than invocation or this error will be triggered. Even that fails:

// same error:
auto test = cast(void*)fun;
May 25, 2022

On Tuesday, 24 May 2022 at 22:18:44 UTC, Adam D Ruppe wrote:

>

There's a big difference between a function and a function pointer.

Could you please clarify in this context?

Fun is basically generated by code like that:

extern (Windows) void* GetProcAddress(void*, const char*);
auto fn = cast(T)GetProcAddress(lib, mangledName.toStringz);
>

If it is a function, you get its address with the & operator. But if it is supposed to be a function pointer, something is wrong with the declaration...

I have no idea what the correct term is but the debugger says fun is:
(if that assert() is removed and it compiles):

Type: void function(...)*
Value: 0x0000000000000000  null

I can get some address with &fun but deferencing then fails:

auto addr = &fun;
assert(*addr); // Error: expression `*addr` of type `extern (C) void(...)` does not have a boolean value
« First   ‹ Prev
1 2 3