How to retrieve array variable from DLL? (Visual C++) - c++

A 3rd party C library contains the following global variable and function:
typedef RtBasis float[4][4];
RI_EXPORT RtBasis RiCatmullRomBasis;
RI_EXPORT void RiBasis(RtBasis u);
I want to retrieve the variable and function from the DLL and use them in my C++ code. When I do the following:
// Get the function.
void (*RiBasis)(RtBasis);
RiBasis = (void (*)(RtBasis))GetProcAddress(h, "RiBasis");
// Get the variable.
RtBasis *RiCatmullRomBasis;
RiCatmullRomBasis = (RtBasis*)GetProcAddress(h, "RiCatmullRomBasis");
// Call the function, passing it the variable.
RiBasis(RiCatmullRomBasis);
Visual C++ gives this compile error on the call to RiBasis:
error C2664: 'void (float [][4])': cannot convert argument 1
from 'RtBasis (*)' to 'float [][4]'
I tried removing one level of indirection from the RiCatmullRomBasis variable:
// Get the variable.
RtBasis RiCatmullRomBasis;
RiCatmullRomBasis = (RtBasis)GetProcAddress(h, "RiCatmullRomBasis");
// Call the function, passing it the variable.
RiBasis(RiCatmullRomBasis);
but that gave me the following on the GetProcAddress call:
error C2440: 'type cast': cannot convert from 'FARPROC' to 'RtBasis'
note: There are no conversions to array types, although there are
conversions to references or pointers to arrays
What's the correct way of declaring the types in my C++ code to make this work?

In the first version make the call as:
RiBasis(*RiCatmullRomBasis);
You need to get the address of the variable (that is what GetProcAddress can return), but the function takes an instance rather than a pointer so you have to dereference the returned pointer.

Related

In my function call I keep getting an error for "primary-expression before 'char'"

I do not understand what is missing in front of char. The line is:
float temp = tinputs(char scale);
I mean I've tried a ton and didn't get passed the error statement. it should be a simple fix though.
From the limited information you've provided I assume you're trying to call function tinputs with argument scale type char.
However you're using a declaration syntax in a call function.
Your code should be like this:
float temp = tinputs(scale);

Returning array from function

Been trying to get this to work for hours with many different methods but still can't get it to work...
Main class:
WinHandle wh;
int* myarr;
myarr = wh.getpos;
cout << "left: " << *(myarr) << endl;
WinHandle.cpp class:
int* WinHandle::getpos(){
int pos[4];
//code
pos[0] = 2;
//code
return pos;
}
WinHandle.h file:
int* getpos();
That's just my last method, tried various others to no avail. Any help?
Keep getting
non-standard syntax; use '&' to create a pointer to member
and
cannot convert from 'int *(__thiscall WinHandle::* )(void)' to 'int *'
A plain array cannot be returned directly from a function.
Use std::array, instead.
Your immediate source of compilation error is wrong syntax. When you are calling the function, you need to call it with parenthesis: wh.getpos(). However, this is a lesser of a problem. A much bigger problem is that you are returning an array which is local to your function. This won't do, this array will be destroyed once you exit the function, and you will end up with a pointer to deleted object. Say 'Hi' to undefined behavior.
To fix the problem, you need to return either std::vector or std::array.
The best solution is to use std::array (or std::vector) because it's the most flexible. Otherwise, you could create the array outside the method, then use a reference parameter to operate on it inside wh.getpos().

D language function call with argument

I am learning D and have mostly experience in C#. Specifically I am trying to use the Derelict3 Binding to SDL2. I have been able to get some basic functionality working just fine but I have become stumped on how to create an array argument for a specific call.
The library contains a call
SDL_RenderDrawLines(SDL_Renderer*, const(SDL_Point)*, int) //Derelict3 Binding
And I have been unable to correctly form the argument for
const(SDL_Point)*
The SDL Documentation for this function states that this argument is an array of SDL_Point, but I am unclear how to create an appropriate array to pass to this function.
Here is an example of what I have at the moment:
void DrawShape(SDL_Renderer* renderer)
{
SDL_Point a = { x:10, y:10};
SDL_Point b = { x:500, y:500};
const(SDL_Point[2]) points = [a,b];
Uint8 q = 255;
SDL_SetRenderDrawColor(renderer,q,q,q,q);
SDL_RenderDrawLines(renderer,points,1);
}
And the compiler complains that I am not passing the correct type of argument for const(SDL_Point)* in points.
Error: function pointer SDL_RenderDrawLines (SDL_Renderer*, const(SDL_Point)*, int)
is not callable using argument types (SDL_Renderer*, const(SDL_Point[2u]), int)
I suspect this is a fundamental misunderstanding on my part so any help would be appreciated.
Arrays aren't implicitly castable to pointers in D. Instead, each array (both static and dynamic) has an intrinsic .ptr property that is a pointer to its first element.
Change your code to:
SDL_RenderDrawLines(renderer,points.ptr,1);
given that the call asks for a pointer and length, I feel it is safer to define you own wrapper:
SDL_RenderDrawLines(SDL_Renderer* rend, const SDL_Point[] points){
SDL_RenderDrawLines(rend,points.ptr,points.length);
}
(why it isn't defined I don't know, any performance hit from the extra function call is just a -inline away from being resolved)

Getting the address of a member function, using CPP

I am working on a school assignment in which I need to build a thread library.
I need pc to hold the address of the given Thread object's run() function.
When I try to cast a member function pointer to address_t (which is really unsigned long int) I get this error
../main.cpp: In function ‘void setup(Thread&)’:
../main.cpp:77:22:
error: invalid cast from type ‘int (Thread::*)()’ to type ‘address_t
{aka unsigned int}’
make: * [main.o] Error 1
Here's the function where I get the error:
void setup(Thread &thread)
{
address_t sp, pc;
sp = (address_t)stack1 + STACK_SIZE - sizeof(address_t);
int (Thread::*temp)() = &Thread::run;
pc = (address_t) temp; // ## LINE 77 ##
sigsetjmp(jbuf[0],1);
(jbuf[0]->__jmpbuf)[JB_SP] = translate_address(sp);
(jbuf[0]->__jmpbuf)[JB_PC] = translate_address(pc);
sigemptyset(&jbuf[0]->__saved_mask);
}
A few clarification:
Thread is a class I wrote, currently doing nothing. It as a int run(void) as its "main" function. address_t, as I said, is typedef unsigned long int
Any ideas as to why I get this error? thanks
I don't think you can do that.
void pointers are pointers to data, and function pointers point to functions. The language does not require functions and data to be in the same address space, so, by way of example and not limitation, on architectures that have them in different address spaces, the two different pointer types will not be comparable.
Take a look at this nice faq. If you cannot convert to void*, then you cannot convert to int or long int
This doesn’t work for two reasons:
function pointers are not compatible with void* (se UmNyobe’s answer), and
in order to use member functions as the thread entry you’d need to store a this pointer as well.
Since you’re using C++ you’ve got a few possibilities though:
Use a base class thread_base defining a virtual function as the thread entry point.
Use a functor as the thread entry point.
In either case you’d need to store this information somewhere and invoke it using the operating system’s thread library.

C++ pthreads - using code I used in C gives me a conversion error

I am running the same exact code that I ran in plain C:
pthread_create(&threads[i], &attr, SomeMethod, ptrChar);
And I get the errors:
error: invalid conversion from
'void*(*)(char'*)' to 'void*(*)(void*)'
error: initializing argument 3 of 'int
pthread_create(__pthread_t**,
__pthread_attr_t* conts*, void*(*)(void*), void*)'
SomeMethod is:
void *SomeMethod(char *direction)
Do I need to do something different in C++? I thought you could just run any C code in C++ and it would work fine?
I am using Cygwin at the moment.
Like it says, they are two different function signatures. You should do:
void *SomeMethod(void* direction) // note, void
{
char* dir = static_cast<char*>(direction); // and get the value
}
C was casting from one function pointer to the other, apparently. Casting one function pointer to another is undefined behavior in C++.
That said, I'm pretty sure POSIX requires that casts between function pointers be well-defined, so you may be able to do this instead:
pthread_create(&threads[i], &attr, // cast the function pointer
reinterpret_cast<void* (*)(void*)>(SomeMethod), ptrChar);
Your thread function needs to be:
void *SomeMethod(void *direction);
And you can cast from void* to char* inside the function.