Sign in to follow this  

Call to DLL always returns zero

This topic is 1113 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi Guys,

 

I have a DLL that I have created (fairly new to DLL's so hopefully a noob question).

 

For some reason GetHeight(nn,mm) always returns zero.

 

If I use the same functions directly in a C++ program it works perfectly.

 

This is how I tested;

 

#include"noise_i.h"
#include<iostream>
int main()
{
 PerlinNoise(1,1,100,1,1);
 for(double i=0;i<2;)
 {
  double v=GetHeight(i,4);
  std::cout<<v<<"\r\n";
  i=i+0.1;
 }
 system("PAUSE");
 return 0;
}

 

So, when the non-dll version, I get a range of values. When use the DLL version I always get zero.

 

#define export extern "C" __declspec (dllexport)
double persistence,frequency,amplitude;
int octaves,randomseed;
double GetValue(double x,double y);
double Interpolate(double x,double y,double a);
double Noise(int x,int y);
export void PerlinNoise(double _persistence,double _frequency,double _amplitude,int _octaves,int _randomseed)
{
 persistence=_persistence;
 frequency=_frequency;
 amplitude=_amplitude;
 octaves=_octaves;
 randomseed=2+_randomseed*_randomseed;
}
export double GetHeight(double x,double y)
{
 //properties of one octave (changing each loop)
 double t=0.0f;
 double _amplitude=1;
 double freq=frequency;
 for(int k=0;k<octaves;k++)
 {
  t+=GetValue(y*freq+randomseed,x*freq+randomseed)*_amplitude;
  _amplitude*=persistence;
  freq*=2;
 }
 return amplitude*t;
}
double GetValue(double x,double y)
{
 int Xint=(int)x;
 int Yint=(int)y;
 double Xfrac=x-Xint;
 double Yfrac=y-Yint;
 //noise values
 double n01 = Noise(Xint-1, Yint-1);
 double n02 = Noise(Xint+1, Yint-1);
 double n03 = Noise(Xint-1, Yint+1);
 double n04 = Noise(Xint+1, Yint+1);
 double n05 = Noise(Xint-1, Yint);
 double n06 = Noise(Xint+1, Yint);
 double n07 = Noise(Xint, Yint-1);
 double n08 = Noise(Xint, Yint+1);
 double n09 = Noise(Xint, Yint);
 double n12 = Noise(Xint+2, Yint-1);
 double n14 = Noise(Xint+2, Yint+1);
 double n16 = Noise(Xint+2, Yint);
 double n23 = Noise(Xint-1, Yint+2);
 double n24 = Noise(Xint+1, Yint+2);
 double n28 = Noise(Xint, Yint+2);
 double n34 = Noise(Xint+2, Yint+2);
 //find the noise values of the four corners
 double x0y0 = 0.0625*(n01+n02+n03+n04) + 0.125*(n05+n06+n07+n08) + 0.25*(n09); 
 double x1y0 = 0.0625*(n07+n12+n08+n14) + 0.125*(n09+n16+n02+n04) + 0.25*(n06); 
 double x0y1 = 0.0625*(n05+n06+n23+n24) + 0.125*(n03+n04+n09+n28) + 0.25*(n08); 
 double x1y1 = 0.0625*(n09+n16+n28+n34) + 0.125*(n08+n14+n06+n24) + 0.25*(n04); 
 //interpolate between those values according to the x and y fractions
 double v1 = Interpolate(x0y0, x1y0, Xfrac); //interpolate in x direction (y)
 double v2 = Interpolate(x0y1, x1y1, Xfrac); //interpolate in x direction (y+1)
 double fin = Interpolate(v1, v2, Yfrac);  //interpolate in y direction
 return fin;
}
double Interpolate(double x, double y, double a)
{
 double negA=1.0-a;
 double negASqr=negA*negA;
 double fac1=3.0*(negASqr)-2.0*(negASqr*negA);
 double aSqr=a*a;
 double fac2=3.0*aSqr-2.0*(aSqr*a);
 return x*fac1+y*fac2; //add the weighted factors
}
double Noise(int x,int y)
{
 int n=x+y*57;
 n=(n<<13)^n;
 int t=(n*(n*n*15731+789221)+1376312589)&0x7fffffff;
 return 1.0-double(t)*0.931322574615478515625e-9;/// 1073741824.0);
}

 

Is there something about using global variables in a DLL that is giving behaviour that I am not anticipating?

 

Thanks in advance :)

 

Share this post


Link to post
Share on other sites
The only difference between the DLL and Non-DLL versions is the following where I have added 'export' to the front of two function declaration. That is all (I just started the program fresh and copied from the working non dll header).
 

export void PerlinNoise(double _persistence, double _frequency, double _amplitude, int _octaves, int _randomseed);
export double GetHeight(double x, double y); 
 
So, I just can't understand why GetHeight always returns 0 for the DLL version. Edited by DarkRonin

Share this post


Link to post
Share on other sites
Ok, after some debugging I have found something weird.
 
If I call this
 
PerlinNoise(1,2,3,4,5);
 
Which simpily does this...
export void PerlinNoise(double _persistence,double _frequency,double _amplitude,int _octaves,int _randomseed)
{
     persistence=_persistence;
     frequency=_frequency;
     amplitude=_amplitude;
     octaves=_octaves;
     randomseed=2+_randomseed*_randomseed;
}
 
and then call this directly after.
 
GetHeight(0,0);
 
Which does this (debugging purposes)
 
export double GetHeight(double x,double y)
{
     // x & y unused for testing purposes
     std::cout<<persistence<<"\t"<<frequency<<"\t"<<amplitude<<"\t"<<octaves<<"\t"<<randomseed<<"\r\n";
 
     return 0;
}
The output is...
 

1   2   3   0   2

 
How can that be?


[edit]
I just found that the funny thing is, if I change the int's to double's in the first function, the DLL then works.

Can you not have int's as inputs for a dll? Edited by DarkRonin

Share this post


Link to post
Share on other sites
It's not clear from your post but what is noise_i.h? If that's the second snippet you show, why do you have the implementation in the header file? That could be why it's screwing up, because it's not using the right function and changing the parameters makes it resolve to the right one. Also, the "extern C" bit should generally go with the function declaration, not its definition. The compiler doesn't care that the function name is mangled, it's the linker that needs to know whether to decorate the function name or not.

Also, generally for DLL's you want your headers to only export stuff if you are actually building the DLL (usually through a BUILDING_XXX preprocessor define or similar). If it is missing, then the header instead configures itself to import the functions and variables, since it is assumed if the define is missing then you are actually trying to use the DLL, so it makes no sense to export anything in that case.

In any case, avoid using global variables from a DLL. Ignoring the fact that mutable global variables is not a great thing to have especially inside a DLL, it is usually more trouble than it is worth with a C interface. Just use functions and local state (like a struct that holds your stuff, if you actually want to go the C interface route, or use COM or whatever).

Share this post


Link to post
Share on other sites

Could be it does not work because you use the removed export keyword from C++ and define it always as __dllspec(dllexport). You need __declspec(dllexport) when compiling the dll and __declspec(dllimport) when using it (or possibly a .def file).

http://msdn.microsoft.com/en-us/library/z4zxe9k8.aspx

http://msdn.microsoft.com/en-us/library/a90k134d.aspx

http://msdn.microsoft.com/en-us/library/8fskxacy.aspx

Edited by wintertime

Share this post


Link to post
Share on other sites

This topic is 1113 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this