I'm trying to recompile my old game which links the Ruby library, but I keep getting this error:
ruby18-mt-static-release.lib(math.obj): error LNK2001: unresolved
external symbol _hypot
Is there any workaround for this that doesn't require me finding the source code to this library and rebuilding it?
I'm using Visual Studio 2010 and the latest DirectX SDK.
I had a similar problem. Apparently hypot used to be a linkable function but is now (I have VS 2010) an inline function that calls _hypot. In math.h this is the only function where this is done. I don't have source for the existing library I am using and it has hypot linked to it so it can't use the inline version. If I just define hypot myself the linker says it is already defined. The following works to fix this:
Edit math.h and comment or ifdef out the inline version of hypot.
Implement hypot as extern "C" double hypot(double x, double y) {return _hypot(x, y);}
Relink
Ugly, but it solved the problem.
You are using the MT-STATIC version of the library. You need to make sure your project (Code Generation->Runtime Library) is also set to multithreaded, not multithreaded DLL. Conversely, you can find the MT-DLL version of the library. Either way, the runtime library (either MT or MTD) must be consistent across your program and all libraries you want to link.
http://msdn.microsoft.com/en-us/library/abx4dbyh(v=vs.80).aspx
This is an old question but I have a new workaround that do not need to modify math.h.
I met a similar issue when I tried to static link 'msvcrt-ruby18-static.lib' into my own dll in Visual Studio 2012 (VS2012). I got the this error:
'unresolved external symbol __imp__hypot referenced in function _math_hypot'
Thanks to Matt's answer, we know it is caused by the change of 'math.h'.
This function:
double hypot(double _X, double _Y)
before vs2010 it was a dll export function declared by keyword like this:
extern "C" __declspec(dllexport) double __cdecl hypot(...)
since vs2010, it became an inline function:
static __inline double __CRTDECL hypot(...)
Luckily in VS2012, the inline function is wrapped by a macro RC_INVOKED. You can try this public domain implantation to let it link:
#define RC_INVOKED
#include <ruby.h>
extern "C" __declspec(dllexport)
double hypot(double x, double y)
{
if (x < 0) x = -x;
if (y < 0) y = -y;
if (x < y) {
double tmp = x;
x = y; y = tmp;
}
if (y == 0.0) return x;
y /= x;
return x * sqrt(1.0+y*y);
}
[NOTICE] My project is a DLL and I use the dllexport keyword directly. It seems the '__imp__' prefix cannot be defined directly. I tried to define a function named __imp__hypot(...) and I failed.
Implement hypot() yourself. It's pretty straightforward:
double hypot(double x, double y) {
double ax = fabs(x), ay = fabs(y);
double xy = x/y, yx = y/x;
return ax > ay
? ax * sqrt(1.0 + yx*yx)
: ay * sqrt(1.0 + xy*xy);
}
Related
I'm looking for a way to remove some header file dependencies. I'm working on a test project which runs a Windows UI in C# on a backend written in LabVIEW compiled to a DLL. Right now, I compile the LabVIEW code to a DLL, then write a middle layer in C++ which imports the LabVIEW DLL, compile the middle layer then import it in the C# project. I have had success testing a different case where the backend is purely C++, but the LabVIEW DLL brings in other dependencies from LabVIEW itself, so that when I try and run the top layer in C#, I get a "cannot find dependency error" in Visual Studio.
I have done some searching and it looks like using forward declaration in my middle layer cpp file is the way to go, but I am unclear about how to make this work. First off, can I do forward declaration since I am not using any pointers or classes at all in my example? If I cannot, what other way can I break the dependencies in my middle layer? I have also tried changing the compiler options of the middle layer DLL to multithread (/MT) as per this post's advice, but that did not resolve the dependency issue.
My test project is a very simple calculator app which does addition and subtraction. The core arithmetic code is written in LabVIEW and the GUI is written in WinUI. The LabVIEW code is as follows,
I then compile my LabVIEW project into a DLL, which also gives me the following header,
LV_calc.h
#include "extcode.h"
#ifdef __cplusplus
extern "C" {
#endif
/*!
* AddTwoDbls
*/
double __cdecl AddTwoDbls(double x, double y);
/*!
* SubtractTwoDbls
*/
double __cdecl SubtractTwoDbls(double x, double y);
MgErr __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module);
void __cdecl SetExecuteVIsInPrivateExecutionSystem(Bool32 value);
#ifdef __cplusplus
} // extern "C"
#endif
Note the #include "extcode.h", which is the LabVIEW dependency located in the LabVIEW program files.
My interface currently loads the LabVIEW header and here is where I suspect I should be doing some forward declaration, but am unsure how. At present, the interface is as follows,
LVcalculatorInterface.h
#pragma once
#ifdef LVCALCINTERFACE_EXPORTS
#define LVCALCINTERFACE_API __declspec(dllexport)
#else
#define LVCALCINTERFACE_API __declspec(dllimport)
#endif
// import and write new interfaces for LV functions
extern "C" LVCALCINTERFACE_API double LVaddDbls (double a, double b);
extern "C" LVCALCINTERFACE_API double LVdiffDbls(double a, double b);
LVcalculatorInterface.cpp
#include "LVcalculatorInterface.h"
#include "pch.h"
#include "LVbuilds/LV_calc.h"
double LVaddDbls(double a, double b) {
return AddTwoDbls(a, b);
}
double LVdiffDbls(double a, double b) {
return SubtractTwoDbls(a, b);
}
Finally, the compiled interface DLL is imported in the C# project
MainWindow.xaml.cs
namespace MyCalculator
{
public class SimpleMathLV
{
[DllImport(#"Interface\LVcalcInterface.dll")]
public static extern double LVaddDbls(double a, double b);
[DllImport(#"Interface\LVcalcInterface.dll")]
public static extern double LVdiffDbls(double a, double b);
}
public sealed partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
private void Add_Button(object sender, RoutedEventArgs e)
{
double sum = SimpleMathLV.LVaddDbls(val_a.Value, val_b.Value);
string sum_string = sum.ToString();
Result.Text = sum_string;
}
private void Subtract_Button(object sender, RoutedEventArgs e)
{
double sum = SimpleMathLV.LVdiffDbls(val_a.Value, val_b.Value);
string sum_string = sum.ToString();
Result.Text = sum_string;
}
}
}
The C# app runs but throws an error when I interact with one of the UI buttons that calls the interface DLL. I get the message,
System.DllNotFoundException: 'Unable to load DLL 'Interface\LVcalcInterface.dll' or one of its dependencies: The specified module could not be found. (0x8007007E)'
So in summary, I need a way to remove the LabVIEW dependency. I think forward declaration may be the solution, but how do I do forward declaration in this situation? Are there other ways I can safely remove the LabVIEW dependency?
This question already has an answer here:
"undefined reference to" errors when linking static C library with C++ code
(1 answer)
Closed 6 years ago.
I'm calling a C static-link library in VS2010 by wrapping the header file with extern "C", but I'm still getting a LNK2001: unresolved external symbol. I'm calling the same .lib file somewhere else with no problems and I'm reusing old code from somewhere else that definitely works. The code I'm using can be found at github.com/toots/microsoft-audio-watermarking. I'm trying to use the "thrabs" function found in hthres.h. I can't think of any obvious reasons it's not working. Here's the example code. thrabs is the c external. Is it possible my variable _fm_lookup which is normally defined in C++ is the problem?
int i;
for(i = 0; i < NFREQ; i++)
_fm_lookup[i] = thrabs((0.5 + i) * (float) fs * 0.5 / (float) NFREQ);
the C static lib is being included by using
extern "C"
{
#include "htres.h"
}
the error is
Error 37 error LNK2001: unresolved external symbol _fm_lookup C:\Users\David\Documents\Projects\watermarking\Builds\VisualStudio2010\internal2003.lib(hthres.obj)
Needed to move the offending code into its own c file and call it from there while using extern "C". Painful lesson learned.
I am trying to expose a C++ DLL to Excel using mac. The DLL was written and compiled with Xcode 4 and I am using Excel 2011.
For simple functions, extern "C" does the work and I am able to use the dylib in Excel. Specifically, if the C++ code is something like
extern "C"
{
double sumC( double a, double b)
{
return a + b;
}
}
and the VBA code is:
Private Declare Function addFunction _
Lib "Macintosh HD:Users:SVM:Documents:Excel:lib:libTestDLLtoVBA.dylib" _
Alias "sumC" (ByVal a As Double, ByVal b As Double) As Double
Function Addition(a As Double, b As Double)
Addition = addFunction(a, b)
End Function
everything works fine. But, I am interested in exposing to Excel more complex code with classes defined in header files - as in the example below - and in that case Excel returns #VALUE!. My C++ code is something like this
header file:
#ifndef TestDLLtoVBA_TestFunction_h
#define TestDLLtoVBA_TestFunction_h
class AdditionVBATest{
public:
AdditionVBATest(){};
AdditionVBATest( double ){ m_AdditionResult = 0.0; }
~AdditionVBATest(){};
void setResult( double nAddition ){ m_AdditionResult = nAddition; }
double getResult(){ return m_AdditionResult; }
void addFunct( double x, double y, double &nResult );
double addFunct( double, double );
private:
double m_AdditionResult;
};
double addFunctionC( double a, double b);
#endif
cpp file:
#include <iostream>
#include "TestFunction.h"
void AdditionVBATest::addFunct(double x, double y, double &nResult)
{
nResult = 0.0;
nResult = x + y;
AdditionVBATest::setResult(nResult);
}
double AdditionVBATest::addFunct( double a, double b )
{
double nResult(0.0);
AdditionVBATest addCompute;
addCompute.AdditionVBATest::addFunct(a, b, nResult);
AdditionVBATest addResult;
return addResult.getResult();
}
And finally this is the file that contains the function I would like to expose to Excel:
#include <iostream>
#include "TestFunction.h"
extern "C"
{
double addFunctionC( double a, double b)
{
AdditionVBATest *resAddition;
double result(0.0);
result = resAddition->AdditionVBATest::addFunct(a, b);
return result;
}
}
I tried to use the same dylib in a C++ app and works fine, so I believe it is something related to exposing the library through VBA.
The VBA code I used is
Private Declare Function addFunction _
Lib "Macintosh HD:Users:SVM:Documents:Excel:lib:libTestDLLtoVBA.dylib" Alias "addFunctionC" _
(ByVal a As Double, ByVal b As Double) As Double
Function Addition(a As Double, b As Double)
Addition = addFunction(a, b)
End Function
Any help would be greatly appreciated.
This is of course not necessary but to simplify I will assume from now on that your header file and both source files are in the same directory, and that all future commands are executed in this directory. Then replace in both source files
#include "TestFunction.h"
with
#include "./TestFunction.h"
Then, compile as follows :
g++ -m32 -Wall -g -c ./TestFunction.cpp -o ./TestFunction.o
g++ -m32 -dynamiclib ./file.cpp ./TestFunction.o -o ./libTestDLLtoVBA.dylib
where
g++ is your gcc. I guess it is clang's one, on my computer it is gcc 5.2.0, but both should work fine
file.cpp is the source file containing the declaration of addFunctionC
the -m32 option asks to produce a 32 bits dylib, as excel/VBA on mac are 32 bits
Now do a nm -gU libTestDLLtoVBA.dylib and you will see a line with _addFunctionC showing that the function addFunctionC is exported indeed.
In the VBA, declare as follows :
Declare Function addFunctionC Lib "/Path/to/your/libTestDLLtoVBA.dylib" (ByVal x As Double, ByVal y As Double) As Double
Function Addition(a As Double, b As Double)
Addition = addFunction(a, b)
End Function
and it should work. This was a great source of inspiration.
Now, if you don't want to used command line and want to use XCode for instance, I would say that the only thing you have to take care of is to ensure that XCode produces a 32 bits dylib, as excel/VBA are 32 bits only on mac OS X. I really think that this 32 bits stuff is your problem.
You likely want to read up on COM automation objects. Sometimes known as "OLE" or "ActiveX". It's essentially a way to expose classes and objects written in C++ to other programming languages.
For scripting environments (VBA and Javascript), the traditional way to do this is by registering a COM object that exposes an IDispatch interface.
Some links to get you started:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms221375(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms221326(v=vs.85).aspx
Don't get hung up on the details of "controls" and embedded UI windows. Foucs on getting a simple COM object class and interface declared in an IDL, generate a typelib, implement a C++ class that implements the interface and IDispatch. ATL (Active Template Library) makes this stuff easy.
I am trying to build a dll to go along with my program in c++. The dll will be a basic library with a bunch of inheritable classes and general utilities, which can then be used dynamically by multiple other applications that will accompany the final product(A Game). I threw something together, only to find that I am recieving I maddening error. It is the famous "error LNK2019: unresolved external symbol". First off, I already found the solution to this, and here is the link: Unresolved External Symbol- Error in guide?
The chosen answer works. If I put my class into only a header file, it compiles perfectly fine, runs, and is all nice and pretty. However, I want to keep the declaration and implementation separate, and if I try to move the implementation to a separate cpp I receive the LNK2019 error. This is due to some kind of inlining, I just want to know how I can bloody fix it before I start tearing my hair out.
Can anyone help me with this? Here is my class:
Header:
#ifndef MYDLLTESTCLASS_H
#define MYDLLTESTCLASS_H
class __declspec( dllexport ) MyDLLTestClass {
public:
MyDLLTestClass();
void setX( int x );
int getX();
private:
int x;
};
#endif // MYDLLTESTCLASS_H
CPP:
#include "MyDLLTestClass.h"
MyDLLTestClass::MyDLLTestClass() {
}
void MyDLLTestClass::setX( int x ) {
this->x = x;
}
int MyDLLTestClass::getX() {
return x;
}
Separate like above, the code wont compile. But if I throw the declaration and implementation together It works, so if I do this:
#ifndef MYDLLTESTCLASS_H
#define MYDLLTESTCLASS_H
class __declspec( dllexport ) MyDLLTestClass {
public:
MyDLLTestClass();
void setX( int x );
int getX();
private:
int x;
};
MyDLLTestClass::MyDLLTestClass() {
}
void MyDLLTestClass::setX( int x ) {
this->x = x;
}
int MyDLLTestClass::getX() {
return x;
}
#endif // MYDLLTESTCLASS_H
It will work. Again, I WANT the declaration and implementation separate.
Here is the build report when I use separate declaration and implementation.
http://pastebin.com/HMEpeEgn
This was actually far easier to solve than I realized; it turns out the it was a visual studio setting all along. First, you need to add the dll project to your current project(Which will be using it). Then you need to right click on you current project and Follow these two pictures:
And then add your dll, which might just need to be check-marked(Mine was simply missing the checkmark).
After that your project will compile perfectly fine! No need for nasty-ass #ifndef macros like every webpage has attempted to portray(which also didn't work mind you)
I have to do one project and I was given dll and a header file with implemented functions needed for the project. I was told just to add the header file to the project but this way i get unresolve externals error if i try to use functions referenced in header. So what needs to be done to make everything work? Visual Studio 2010.
Here are the files i have: http://www.ipix.lt/images/33871682.png
And this is header file:
#ifndef __BIM482_RADAR__
#define __BIM482_RADAR__
int BIM482OpenRadar();
int BIM482AddPlane(double x, double y);
int BIM482SetPlaneColor(int planeidx, int coloridx);
int BIM482SetPlanePos(int planeidx, double x, double y);
void BIM482UpdateRadar();
#endif // __BIM482_RADAR__
I need to initiate gui with OpenRadar and pass information with those functions. How to start this thing?
You don't have a .lib-file to link against.
Maybe this can help you
http://www.coderetard.com/2009/01/21/generate-a-lib-from-a-dll-with-visual-studio/
or this:
http://support.microsoft.com/default.aspx?scid=kb;en-us;131313
or this:
http://www.asawicki.info/news_1420_generating_lib_file_for_dll_library.html
when you have generated the lib-file ,you must use __declspec(dllimport) on yuor functions in the header file.
An alternative to all of the above is to use LoadLibrary(...) in your source and write wrapper function for those function in the dll and call those dll funcions via GetProcAddress(...).
struct
{
HMODULE hDll;
int (*BIM482OpenRadar) ();
int (*BIM482AddPlane) (double x, double y);
int (*BIM482SetPlaneColor) (int planeidx, int coloridx);
int (*BIM482SetPlanePos) (int planeidx, double x, double y);
void (*BIM482UpdateRadar) ();
} dll_funcs = {0};
bool ExitRadar( LPCTSTR szDllPath )
{
if (dll_funcs.hDll)
FreeLibrary( dll_funcs.hDll );
return true;
}
bool InitRadar( LPCTSTR szDllPath )
{
if (dll_funcs.hDll)
return true;
dll_funcs.hDll = LoadLibrary( szDllPath );
if (!dll_funcs.hDll)
return false;
dll_funcs.BIM482OpenRadar = (int(*)())GetProcAddress( dll_funcs.hDll ,("BIM482OpenRadar") );
dll_funcs.BIM482AddPlane = (int(*)(double,double))GetProcAddress( dll_funcs.hDll ,("BIM482AddPlane") );
dll_funcs.BIM482SetPlaneColor = (int(*)(int,int))GetProcAddress( dll_funcs.hDll ,("BIM482SetPlaneColor") );
dll_funcs.BIM482SetPlanePos = (int(*)(int,double,double))GetProcAddress( dll_funcs.hDll ,("BIM482SetPlanePos") );
dll_funcs.BIM482UpdateRadar = (void(*)())GetProcAddress( dll_funcs.hDll ,("BIM482UpdateRadar") );
return true;
}
int BIM482OpenRadar ()
{ return (*dll_funcs.BIM482OpenRadar)(); };
int BIM482AddPlane (double x, double y)
{ return (*dll_funcs.BIM482AddPlane)( x ,y ); }
int BIM482SetPlaneColor (int planeidx, int coloridx )
{ return (*dll_funcs.BIM482SetPlaneColor)( planeidx ,coloridx ); }
int BIM482SetPlanePos (int planeidx, double x, double y)
{ return (*dll_funcs.BIM482SetPlanePos)( planeidx ,x ,y ); }
void BIM482UpdateRadar ()
{ return (*dll_funcs.BIM482UpdateRadar)(); }
There is a windows call that loads a DLL into your image. You can either add it to the compile setup in Visual Studio, or load it dynamically.
The easiest thing is probably to do it at compile time; google "Visual Studio llinking options".
You'll need to export the function from dll, while import the function from your exe. Like:
#if defined(XYZLIBRARY_EXPORT) // inside DLL
#define XYZAPI __declspec(dllexport)
#else // outside DLL
#define XYZAPI __declspec(dllimport)
#endif // XYZLIBRARY_EXPORT
int XYZAPI BIM482OpenRadar();
int XYZAPI BIM482AddPlane(double x, double y);
int XYZAPI BIM482SetPlaneColor(int planeidx, int coloridx);
int XYZAPI BIM482SetPlanePos(int planeidx, double x, double y);
void XYZAPI BIM482UpdateRadar();
In DLL, i suggest to add a macro, and add XYZLIBRARY_EXPORT in pre-processor
It will export all of your function.
In EXE, import the function, without adding pre-processor, as it will import the function by default.
In addition to including header files, you need to link your program with the corresponding libraries. From your screenshot, you seem to have .a files, which are indeed libraries, but unfortunately they are meant for use with the GCC toolchain and will not work with Visual Studio. You either need to get .lib files if you must use Visual Studio, or otherwise switch to a GCC port such as MinGW.
You may use windows API LoadLibrary to load the dll during runtime, followed by GetProcAddress to retrieve function address. With the function address is retrieved, you need to declare the method signature so that compiler know how to call given function.
Below is a sample code for how to "link" to function in Dll:
HINSTANCE m_hExtDll = LoadLibrary( "SDL.dll" )
if (m_hExtDll)
{
FARPROC m_pfnOpenRadar = GetProcAddress(m_hExtDll, "BIM482OpenRadar")
if (m_pfnOpenRadar)
{
typedef int (*OPENRADARFUNC)();
OPENRADARFUNC fnOpenRadar = (OPENRADARFUNC)m_pfnOpenRadar;
int iRetCode = fnOpenRadar();
}
}
Do note that functions exported are subject to name mangling and you can verify the function name using third-party utility like Dependency Walker.