Trivial Windows DLL built with GHC 64-bit does not link - c++

For a proof-of-concept, I want to link some trivial Haskell code into my Visual C++ application (using Visual Studio 2013). Building with GHC 7.8.3 32-bit works, but building with GHC 7.8.4 64-bit does not (notice the slight discrepancy in GHC version too).
There are 3 files: Grep.hs and StartEnd.c are built with GHC to form a DLL. main.cpp is built with Visual Studio 2013 and attempts to link in the DLL library.
I am building the DLL from this:
> ghc -shared -O -optc-O -o Grep.dll StartEnd.c Grep.hs
And from within Visual Studio, I simply link against Grep.dll.a and include C:\Program Files\MinGHC-7.8.4\ghc-7.8.4\lib\include, but linking fails with
1>main.obj : error LNK2001: unresolved external symbol _HsEnd
1>main.obj : error LNK2001: unresolved external symbol _freegrep
1>main.obj : error LNK2001: unresolved external symbol _grep
1>main.obj : error LNK2001: unresolved external symbol _HsStart
1>C:\Code\Grep\dist\Win32\Release\Grep.exe : fatal error LNK1120: 4 unresolved externals
The exact same process works when I build with 32-bit, but not 64-bit. What could I be doing wrong? (I am building a 64-bit app when attempting to link the 64-bit library.)
Source files:
Grep.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Grep where
import Foreign
import Foreign.C.String
import Data.List (isInfixOf)
filterlines f = unlines . filter f . lines
grep :: CString -> CString -> IO CString
grep i s = do
ii <- peekCString i
ss <- peekCString s
newCString $ (filterlines (isInfixOf ii)) ss
freegrep :: CString -> IO ()
freegrep s = free s
foreign export ccall grep :: CString -> CString -> IO CString
foreign export ccall freegrep :: CString -> IO ()
StartEnd.c
#include <Rts.h>
void HsStart()
{
int argc = 1;
char* argv[] = {"ghcDll", NULL}; // argv must end with NULL
// Initialize Haskell runtime
char** args = argv;
hs_init(&argc, &args);
}
void HsEnd()
{
hs_exit();
}
main.cpp
#include <HsFFI.h>
#include <Grep_stub.h>
#include <iostream>
extern "C" {
void HsStart();
void HsEnd();
}
int main(int argc, char* argv[])
{
HsStart();
HsPtr str;
str = grep("test", "This is a test\nwith many lines\nand it failed\nand the test passed");
if (str)
{
std::cout << (char*) str;
freegrep(str);
}
HsEnd();
return 0;
}

Thanks to the comments, I added the actual error output to the post. This caused me to notice that Visual Studio's confusing configuration management interface had bit me once again. It was still trying to build the Win32 version even though my configuration setting said x64. Long story short, it's working!

Related

LLVM: linking errors in VS 2015

I have downloaded source and built LLVM using CMake and VS 2015.
My sample program is the following:
#include <iostream>
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/CFG.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
int main(int argc, char **argv) {
if (argc < 2) {
errs() << "Usage: " << argv[0] << " <IR file>\n";
return 1;
}
// Parse the input LLVM IR file into a module.
SMDiagnostic Err;
LLVMContext TheContext;
std::unique_ptr<Module> Mod = parseIRFile(argv[1], Err, TheContext);
if (!Mod) {
Err.print(argv[0], errs());
return 1;
}
// ... use module
}
I get the following linking errors after having included the LLVM lib directory in the linker library path:
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "public: __thiscall llvm::LLVMContext::LLVMContext(void)" (??0LLVMContext#llvm##QAE#XZ) referenced in function _main LLVM_IRReader c:\Users\nlykkei\documents\visual studio 2015\Projects\LLVM_IRReader\LLVM_IRReader\Main.obj 1
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "public: __thiscall llvm::Module::~Module(void)" (??1Module#llvm##QAE#XZ) referenced in function "public: void * __thiscall llvm::Module::`scalar deleting destructor'(unsigned int)" (??_GModule#llvm##QAEPAXI#Z) LLVM_IRReader c:\Users\nlykkei\documents\visual studio 2015\Projects\LLVM_IRReader\LLVM_IRReader\Main.obj 1
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "class llvm::raw_ostream & __cdecl llvm::errs(void)" (?errs#llvm##YAAAVraw_ostream#1#XZ) referenced in function _main LLVM_IRReader c:\Users\nlykkei\documents\visual studio 2015\Projects\LLVM_IRReader\LLVM_IRReader\Main.obj 1
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "public: void __thiscall llvm::SMDiagnostic::print(char const *,class llvm::raw_ostream &,bool,bool)const " (?print#SMDiagnostic#llvm##QBEXPBDAAVraw_ostream#2#_N2#Z) referenced in function _main LLVM_IRReader c:\Users\nlykkei\documents\visual studio 2015\Projects\LLVM_IRReader\LLVM_IRReader\Main.obj 1
Does anyone know how to resolve these errors? I see, e.g., raw_ostream.obj in the LLVM build directory...
I've never used LLVM but based on your error messages, the linker didn't succeed in finding the LLVM class implementations.
To my point of view, including the LLVM lib directory is not enough. You have to include also the LLVM libraries (.lib which implement the LLVM classes) you want to link with.

Adding htmlhelp to project

I'm trying, without much luck, to add chm options to an existing project.
Main.cpp has this:
#include "HtmlHelp.h"
int OpenHelp(LPTSTR arg1)
{
HWND _Hhdl = HtmlHelp(GetDesktopWindow(), arg1, HH_DISPLAY_TOPIC, NULL);
return 1;
}
htmlhelp.lib is set in Linker/Input/additional Dependencies.
The error I'm getting is:
main.obj : error LNK2019: unresolved external symbol _HtmlHelpW#16 referenced in function "int __cdecl OpenHelp(wchar_t *)" (?OpenHelp##YAHPA_W#Z)
I'm new to C++ so I'm assuming my function is at fault somehow.
The idea was the function would be passed a sting in the "C:\Help.chm\::/Topic.html" format.

Linker error when installing MessagePack implementation for C and C++

I'm following the instructions, which tell me to download msgpack 0.5.4 for C & C++.
On Windows, download source package from here and extract it. Open msgpack_vc8.vcproj or msgpack_vc2008 file and build it using batch build. It builds libraries in lib/ folder and header files in include/ folder.
You can build using command line as follows:
vcbuild msgpack_vc2008.vcproj
dir lib % DLL files are here
dir include % header files are here
vcbuild msgpack_vc2008.vcproj has been replaced by MSBuild msgpack_vc8.vcxproj. I used Visual studio 2012 to convert the project to have the correct .vcxproj for this. Batch build in Visual studio and running MSBuild gives the same result, so I will speak for both of them from this point on.
After the project is converted, I noticed the project was set to output to .lib, rather than .dll, so I altered that setting to match my needs. When compiling there was one small error:
...\microsoft visual studio 11.0\vc\include\stdint.h(8): error C2371: 'int8_t' : redefinition; different basic types
...msgpack-0.5.4\src\msgpack\sysdep.h(23) : see declaration of 'int8_t'
So I changed the line
typedef __int8 int8_t;
to
typedef signed __int8 int8_t;
which solves that minor issue. But then we arrive at where I'm at now. This linker error:
objectc.obj : error LNK2019: unresolved external symbol __imp__ntohl#4 referenced in function _msgpack_pack_array
unpack.obj : error LNK2001: unresolved external symbol __imp__ntohl#4
objectc.obj : error LNK2019: unresolved external symbol __imp__ntohs#4 referenced in function _msgpack_pack_array
unpack.obj : error LNK2001: unresolved external symbol __imp__ntohs#4
...\msgpack-0.5.4\Debug\MessagePack.dll : fatal error LNK1120: 2 unresolved externals
I've searched for parts of this error:
In sysdep.h:
#define _msgpack_be16(x) ntohs(x)
#define _msgpack_be32(x) ntohl(x)
In object.c:
case MSGPACK_OBJECT_ARRAY:
{
int ret = msgpack_pack_array(pk, d.via.array.size);
if(ret < 0) { return ret; }
msgpack_object* o = d.via.array.ptr;
msgpack_object* const oend = d.via.array.ptr + d.via.array.size;
for(; o != oend; ++o) {
ret = msgpack_pack_object(pk, *o);
if(ret < 0) { return ret; }
}
In unpack.c:
static inline int template_callback_array(unpack_user* u, unsigned int n, msgpack_object* o)
{
o->type = MSGPACK_OBJECT_ARRAY;
o->via.array.size = 0;
o->via.array.ptr = (msgpack_object*)msgpack_zone_malloc(u->z, n*sizeof(msgpack_object));
if(o->via.array.ptr == NULL) { return -1; }
return 0;
}
And that's about all I know. If there's another way of how to obtain the .dll, that would be helpful too. Thank you in advance. :)
You need to link the ws2_32.lib library since ntohl is a winsocket API function.
That should fix the problem!

Calling MATLAB from C++ errors: unresolved external symbol

I encounter several errors when calling my MATLAB function from C++. The main idea is: firstly compile a MATLAB function and generate DLL file, and then include .h and .lib files in C++. Finally, write .cpp to test and call the function. Here's my detailed steps and please tell me where I'm wrong.
(Using MATLAB 2012b and Visual C++ 2008, Windows 7 64-bit)
In MATLAB:
mbuild -setup and mex -setup to set Visual Microsoft Visual C++ 2008 SP1 as the compiler.
Create MyAdd.m in folder C:\Users\WangYudong\Documents\MATLAB\MyAdd_M and the function is like:
function [c] = MyAdd(a, b)
c = a + b;
mcc -W cpplib:libMyAdd -T link:lib MyAdd to compile MyAdd.m and generate several files including libMyAdd.dll, libMyAdd.h, libMyAdd.lib and other files.
In C++
Select VC++ Directories → Include files to add E:\MATLAB\R2012b\extern\include.
Select VC++ Directories → Library files to add
E:\MATLAB\R2012b\extern\lib\win64\microsoft and
C:\Users\WangYudong\Documents\MATLAB\MyAdd_M.
Select Linker → Input → Additional Dependencies to add new entries:
mclmcr.lib
mclmcrrt.lib
libmx.lib
libmat.lib
libMyAdd.lib
Create a new MyAdd_test.cpp and put libMyAdd.dll, libMyAdd.h and libMyAdd.lib in the same folder. Add libMyAdd.h in Header Files, libMyAdd.h and libMyAdd.lib in Resource Files.
Code of MyAdd_test.cpp is like:
#include "mclmcr.h"
#include "matrix.h"
#include "mclcppclass.h"
#include "libMyAdd.h"
int main() {
double a = 6;
double b = 9;
double c;
// initialize lib
if( !libMyAddInitialize()) {
std::cout << "Could not initialize libMyAdd!" << std::endl;
return -1;
}
// allocate space
mwArray mwA(1, 1, mxDOUBLE_CLASS);
mwArray mwB(1, 1, mxDOUBLE_CLASS);
mwArray mwC(1, 1, mxDOUBLE_CLASS);
// set data
mwA.SetData(&a, 1);
mwB.SetData(&b, 1);
// use function: MyAdd
MyAdd(1, mwC, mwA, mwB);
// get data
c = mwC.Get(1, 1);
printf("c is %f\n", c);
// terminate the lib
libMyAddTerminate();
// terminate MCR
mclTerminateApplication();
return 0;
}
At last, the result is
Compiling...
MyAdd_test.cpp
Linking...
MyAdd_test.obj : error LNK2019: unresolved external symbol _mclTerminateApplication_proxy referenced in function _main
MyAdd_test.obj : error LNK2019: unresolved external symbol _libMyAddTerminate referenced in function _main
MyAdd_test.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) void __cdecl MyAdd(int,class mwArray &,class mwArray const &,class mwArray const &)" (__imp_?MyAdd##YAXHAAVmwArray##ABV1#1#Z) referenced in function _main
MyAdd_test.obj : error LNK2019: unresolved external symbol _libMyAddInitialize referenced in function _main
MyAdd_test.obj : error LNK2019: unresolved external symbol _mclGetMatrix referenced in function "public: __thiscall mwArray::mwArray(unsigned int,unsigned int,enum mxClassID,enum mxComplexity)" (??0mwArray##QAE#IIW4mxClassID##W4mxComplexity###Z)
MyAdd_test.obj : error LNK2019: unresolved external symbol _mclcppGetLastError referenced in function "public: static void __cdecl mwException::raise_error(void)" (?raise_error#mwException##SAXXZ)
MyAdd_test.obj : error LNK2019: unresolved external symbol _mclcppCreateError referenced in function "public: __thiscall mwException::mwException(void)" (??0mwException##QAE#XZ)
MyAdd_test.obj : error LNK2019: unresolved external symbol _ref_count_obj_addref referenced in function "public: __thiscall mwException::mwException(class mwException const &)" (??0mwException##QAE#ABV0##Z)
MyAdd_test.obj : error LNK2019: unresolved external symbol _ref_count_obj_release referenced in function "public: virtual __thiscall mwException::~mwException(void)" (??1mwException##UAE#XZ)
MyAdd_test.obj : error LNK2019: unresolved external symbol _error_info_get_message referenced in function "public: virtual char const * __thiscall mwException::what(void)const " (?what#mwException##UBEPBDXZ)
MyAdd_test.obj : error LNK2019: unresolved external symbol _array_ref_getV_int referenced in function "public: class mwArray __cdecl mwArray::GetPromoted(unsigned int,...)" (?GetPromoted#mwArray##QAA?AV1#IZZ)
MyAdd_test.obj : error LNK2019: unresolved external symbol _array_ref_set_numeric_mxDouble referenced in function "public: void __thiscall mwArray::SetData(double *,unsigned int)" (?SetData#mwArray##QAEXPANI#Z)
MyAdd_test.obj : error LNK2019: unresolved external symbol _array_ref_get_numeric_mxDouble referenced in function "public: __thiscall mwArray::operator double(void)const " (??BmwArray##QBENXZ)
C:\Users\WangYudong\Documents\Visual Studio 2008\Projects\MyAdd_C\Debug\MyAdd_C.exe : fatal error LNK1120: 13 unresolved externals
Actually, the work above is my test to call a custom MATLAB function from C++. My following work is to convert a MATLAB program to C++, which contains image processing functions like imread, edge, strel, etc. I've tried MATLAB Coder, but it can't convert MATLAB functions. So I try the method above. Is it an efficient way to convert those functions or should I implement them using OpenCV?
Before you start, make sure you have a supported compiler installed. That would be Visual C++ and possibly Windows SDK if you are using VS Express edition on a 64-bit Windows. Next you need to configure MATLAB by running these steps at least once:
>> mex -setup
>> mbuild -setup
Now given the following simple function:
MyAdd.m
function c = MyAdd(a,b)
c = a + b;
end
We want to build a C++ shared library using the MATLAB Compiler mcc:
>> mcc -N -W cpplib:libMyAdd -T link:lib MyAdd.m -v
This will produce a couple of files including a header file, a DLL, and an import library:
libMyAdd.h
libMyAdd.dll
libMyAdd.lib
Next we create a C++ program to test the above library:
MyAdd_test.cpp
#include "libMyAdd.h"
int main()
{
// initialize MCR and lib
if (!mclInitializeApplication(NULL,0)) {
std::cerr << "could not initialize the application" << std::endl;
return -1;
}
if(!libMyAddInitialize()) {
std::cerr << "Could not initialize the library" << std::endl;
return -1;
}
try {
// create input
double a[] = {1.0, 2.0, 3.0, 4.0};
double b[] = {5.0, 6.0, 7.0, 8.0};
mwArray in1(2, 2, mxDOUBLE_CLASS, mxREAL);
mwArray in2(2, 2, mxDOUBLE_CLASS, mxREAL);
in1.SetData(a, 4);
in2.SetData(b, 4);
// call function
mwArray out;
MyAdd(1, out, in1, in2);
// show result
std::cout << "in1 + in2 = " << std::endl;
std::cout << out << std::endl;
double c[4];
out.GetData(c, 4);
for(int i=0; i<4; i++) {
std::cout << c[i] << " " << std::endl;
}
} catch (const mwException& e) {
std::cerr << e.what() << std::endl;
return -2;
} catch (...) {
std::cerr << "Unexpected error thrown" << std::endl;
return -3;
}
// cleanup
libMyAddTerminate();
mclTerminateApplication();
return 0;
}
We could compile this program right from inside MATLAB using:
>> mbuild MyAdd_test.cpp libMyAdd.lib -v
>> !MyAdd_test
We could also compile it ourselves using Visual Studio. We start by creating a native console application, then set the project settings as follows:
From the menu, select "Project > Properties" and apply the settings to "All configurations" (both debug and release targets)
Under C/C++ properties, set the "Additional Include Directories" by adding both the directory containing the generated header file libMyAdd.h, in addition to the directory containing MATLAB's header files:
$matlabroot\extern\include
Similarly under "Linker", set the "Additional Library Directories". That would be the same directory as before containing libMyAdd.lib, as well as in my case:
$matlabroot\extern\lib\win32\microsoft
Then go to "Linker > Input" and add the following inside "Additional Dependencies":
libMyAdd.lib
mclmcrrt.lib
Finally under "Debugging > Environment", you might want to extend the PATH environment variable to include the directory containing the generated libMyAdd.dll file. That way you can directly hit F5 to compile run the program directly from inside VS. This will be something like:
PATH=%PATH%;C:\path\to\output\folder
If you do this kind of thing often, you could create a property sheet once, which could then be reused in other VC++ projects. See this answer for an example.

Linker error using openCV with fftw3 Visual Studio 2010

I'm having trouble trying to implement fftw3 with openCV in the same project.
I'm new to c/c++ and any help will be much appreciated.
The following is just a sample code i used:
#include "fftw3.h"
#include <stdlib.h>
int main(){
fftw_complex *in, *out;
fftw_plan p;
int N=8;
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
for(int i=0; i<N; i++){
in[i][0]=i;
in[i][1]=0;
}
fftw_execute(p);
for(int i=0; i<N; i++){
printf("R->%f\tI->%f\n", out[i][0], out[i][1]);
}
system("pause");
fftw_destroy_plan(p);
fftw_free(in); fftw_free(out);
}
The code is compiling fine when its in its own project.
But when I'm trying to link the fftw3 and openCV together i get a linker error:
1>video.obj : error LNK2001: unresolved external symbol _fftw_destroy_plan
1>video.obj : error LNK2001: unresolved external symbol _fftw_execute
1>video.obj : error LNK2001: unresolved external symbol _fftw_plan_dft_2d
1>video.obj : error LNK2001: unresolved external symbol _fftw_malloc
1>video.obj : error LNK2001: unresolved external symbol _fftw_free
1>D:\C WorkSpace\Viedo_CV\Video test\Release\Video test.exe : fatal error LNK1120: 5 unresolved externals
1>
1>Build FAILED.
I double checked all the linker configurations and they seem to be fine(as i said all is working well when in a separate projects).
The openCV library is working fine.
Unfortunately I can't post my real code.
All the openCV i use is in:
#include <opencv\\cv.h>
#include <opencv\\highgui.h>
#include <windows.h>
Any help will be much appreciated.
I got it figured out, when I installed openCV I created an environmental variable to the openCV build location and added the openCV DLL's location to the Path variable.
What i didn't notice is that I added the x86 version of the DLL's to the Path variable and my project was setup as x64, the reason it worked in another project is because I copied the x64 DLL's to the project folder it self.
All worked fine after I edited the Path to the correct x64 DLL's location.