C++: Explicit DLL Loading: First-chance Exception on non "extern C" functions - exception

I am having trouble importing my C++ functions. If I declare them as C functions I can successfully import them. When explicit loading, if any of the functions are missing the extern as C decoration I get a the following exception:
First-chance exception at 0x00000000 in cpp.exe: 0xC0000005: Access violation.
DLL.h:
extern "C" __declspec(dllimport) int addC(int a, int b);
__declspec(dllimport) int addCpp(int a, int b);
DLL.cpp:
#include "DLL.h"
int addC(int a, int b) {
return a + b;
}
int addCpp(int a, int b) {
return a + b;
}
main.cpp:
#include "..DLL/DLL.h"
#include <stdio.h>
#include <windows.h>
int main() {
int a = 2;
int b = 1;
typedef int (*PFNaddC)(int,int);
typedef int (*PFNaddCpp)(int,int);
HMODULE hDLL = LoadLibrary(TEXT("../Debug/DLL.dll"));
if (hDLL != NULL)
{
PFNaddC pfnAddC = (PFNaddC)GetProcAddress(hDLL, "addC");
PFNaddCpp pfnAddCpp = (PFNaddCpp)GetProcAddress(hDLL, "addCpp");
printf("a=%d, b=%d\n", a,b);
printf("pfnAddC: %d\n", pfnAddC(a,b));
printf("pfnAddCpp: %d\n", pfnAddCpp(a,b)); //EXCEPTION ON THIS LINE
}
getchar();
return 0;
}
How can I import c++ functions for dynamic loading? I have found that the following code works with implicit loading by referencing the *.lib, but I would like to learn about dynamic loading.
Thank you to all in advance.
Update:
bindump /exports
1 00011109 ?addCpp##YAHHH#Z = #ILT+260(?addCpp##YAHHH#Z)
2 00011136 addC = #ILT+305(_addC)
Solution:
Create a conversion struct as
found here
Take a look at the
file exports and copy explicitly the
c++ mangle naming convention.
PFNaddCpp pfnAddCpp = (PFNaddCpp)GetProcAddress(hDLL, "?addCpp##YAHHH#Z");

Inevitably, the access violation on the null pointer is because GetProcAddress() returns null on error.
The problem is that C++ names are mangled by the compiler to accommodate a variety of C++ features (namespaces, classes, and overloading, among other things). So, your function addCpp() is not really named addCpp() in the resulting library. When you declare the function with extern "C", you give up overloading and the option of putting the function in a namespace, but in return you get a function whose name is not mangled, and which you can call from C code (which doesn't know anything about name mangling.)
One option to get around this is to export the functions using a .def file to rename the exported functions. There's an article, Explicitly Linking to Classes in DLLs, that describes what is necessary to do this.

It's possible to just wrap a whole header file in extern "C" as follows. Then you don't need to worry about forgetting an extern "C" on one of your declarations.
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllimport) int addC(int a, int b);
__declspec(dllimport) int addCpp(int a, int b);
#ifdef __cplusplus
} /* extern "C" */
#endif
You can still use all of the C++ features that you're used to in the function bodies -- these functions are still C++ functions -- they just have restrictions on the prototypes to make them compatible with C code.

Related

Why NVCC is unable to match function definition to an existing declaration?

I have this files that produce the following error when compiling with nvcc
error C2244: 'TemplateClass<N>::print': unable to match function definition to an existing declaration
note: see declaration of 'TemplateClass<N>::print'
note: definition note: 'void TemplateClass<N>::print(const std::string [])'
note: existing declarations note: 'void TemplateClass<N>::print(const std::string [N])'
Template.h
#pragma once
#include <string>
#include <iostream>
template <unsigned int N>
class TemplateClass
{
private:
std::string name;
public:
TemplateClass();
TemplateClass(const std::string& name);
void print(const std::string familyName[N]);
};
#include "template.inl"
Template.inl
template <unsigned int N>
TemplateClass<N>::TemplateClass()
{
name = "Unknown";
}
template <unsigned int N>
TemplateClass<N>::TemplateClass(const std::string& name)
{
this->name = name;
}
template <unsigned int N>
void TemplateClass<N>::print(const std::string familyName[N])
{
std::cout << "My name is " << name << " ";
for (auto i = 0; i < N; i++)
std::cout << familyName[i] << " ";
std::cout << std::endl;
}
consume_template.cu
#include "template.h"
void consume_template_gpu()
{
TemplateClass<3> obj("aname");
std::string namesf[3];
namesf[0] = "un";
namesf[1] = "deux";
namesf[2] = "trois";
obj.print(namesf);
}
I am using VS2017 15.4.5, later versions failed to create the project with CMake.
The project was created with CMake like this
cmake_minimum_required(VERSION 3.10)
project(template_inl_file LANGUAGES CXX CUDA)
set (lib_files template.h consume_template.cu)
add_library(template_inl_file_lib ${lib_files})
Just out of curiosity , try using std::string namesf = {"un","deux","trois"}; It seems like a compiler issue. Trying different formats might help compiler to understand better. Otherwise code seems to be ok.
Maybe you're missing some linkage with CMake. Also try compiling straight from VS2017 without using CMake by creating a CUDA project.
What's happening is that the array is decaying into a pointer and the size of the array is lost during compilation. So this
template <unsigned int N>
void TemplateClass<N>::print(const std::string familyName[N]);
will be actually turned into this
template <unsigned int N>
void TemplateClass<N>::print(const std::string* familyName);
as we can see there is no way for the compiler to know that it has to generate different functions depending on the size of the array (i.e. the template parameter N).
To solve this we can use an old trick to avoid array decay like this
template <unsigned int N>
void TemplateClass<N>::print(const std::string (&familyName)[N]);
Now the size N is present through the compilation and the compiler knows there are different functions to be generated. I guess, as pointed out in the comments of the question that NVCC produces code that VS does not produce by itself and then it does not know how to handle it.
More info on the topic on the following links
http://pointer-overloading.blogspot.ch/2013/09/c-template-argument-deduction-to-deduce.html
http://en.cppreference.com/w/cpp/language/template_argument_deduction
https://theotherbranch.wordpress.com/2011/08/24/template-parameter-deduction-from-array-dimensions/

Auto Conversion of Structs to Dicts in Cython

So, if you've got a header file.
%%file test.h
struct mystruct{
int i;
int j;
};
And then you wrap it in Cython:
cdef extern from "test.h" nogil:
struct mystruct:
int i
int j
And some function that returns back out to Py:
def spit_out_dict():
return mystruct(5,10)
Cython correctly automatically generates a dict wrapper. However, when I wrap the original C header in a namespace, I haven't been able to get get Cython to still generate the dict wrapper correctly, something along these lines:
%%file test2.h
namespace outerspace{
struct mystruct{
int i;
int j;
};
}
And Cython/Python:
cdef extern from "test2.h" namespace "outerspace" nogil:
struct mynewstruct:
int i
int j
def spit_out_dict():
return mynewstruct(5,10)
This won't compile -- lots of namespace complaint errors -- anyone experienced this before?
Your problem is that Cython seems to only expect namespaces to be used with cppclass. For structs, it generates some functions but just copies the full namespaced name in, causing errors:
static PyObject* __pyx_convert__to_py_outerspace::mystruct(struct outerspace::mystruct s);
^
py_bit.cpp: In function ‘PyObject* __pyx_pf_6py_bit_spit_out_dict(PyObject*)’:
py_bit.cpp:721:15: error: ‘__pyx_convert__to_py_outerspace’ has not been declared
where it's trying to create a function called __pyx_convert__to_py_<classname>. (I think this might be worth submitting a bug report for.)
The trick in such circumstances is usually to lie to Cython. I create three files:
// test2.hpp
namespace outerspace{
struct mystruct{
int i;
int j;
};
}
,
// test2_cy.hpp - a wrapper file purely for Cython's benefit
#include "test2.hpp"
using outerpsace::mystruct;
and the cython file
cdef extern from "test2_cy.hpp": # (I didn't test with "nogil", but it's probably fine...)
struct mynewstruct:
int i
int j
def spit_out_dict():
# for some reason using "return mystruct(5,10)" doesn't work, but this does...
cdef mystruct a = mystruct(5,10)
return a
This is a bug in Cython, fixed at https://github.com/cython/cython/commit/fa946e8435a4dcc3497fc7b0f4e87256d40844ba

how can the vim script(clang_complete ) complete function ,template?

In the clang_complete.txt(the help file), it shows these in clang_complete-compl_kinds:
2.Completion kinds *clang_complete-compl_kinds*
Because libclang provides a lot of information about completion, there are
some additional kinds of completion along with standard ones (see >
:help complete-items for details):
'+' - constructor
'~' - destructor
'e' - enumerator constant
'a' - parameter ('a' from "argument") of a function, method or template
'u' - unknown or buildin type (int, float, ...)
'n' - namespace or its alias
'p' - template ('p' from "pattern")
the question are:
1. i cannot access the complete-items(no this file)
2. can someone tell me how to use the parameter '+' 'a' and so on.
3. or can you tell me how to show function parameters when ( is typed.
thanks!
(forgive my poor english)
It's been a long time, but i'll answer to help future visitors.
I don't fully understand your questions, but I'll answer the 3rd one. Clang complete only launches automatic suggestion/completion when writing '.', '->' or '::', but you can launch it manually.
I use it this way. In this source:
#include <iostream>
using namespace std;
void ExampleFunc (float foo, int &bar)
{
cout << foo;
bar++;
}
int main (int argc, char **argv)
{
int a(0);
Exa[cursor here]
return 0;
}
Writing "Exa" you can press <C-X><C-U> and you will get a preview window with:
Example (float foo, int &bar)
and a completion window (the same that appears when you press <C-N> (CTRL-N) in insert mode) with:
Example f void Example(float foo, int &bar)
If there are several matches, you can move down or up with <C-N> or <C-P> and complete with <CR> (enter).
The completion is not perfect, but it should work for many other cases, for example (as you mentioned) templates:
#include <vector>
using namespace std;
int main (int argc, char **argv)
{
struct MyType {int asdf; float qwer;};
vector<MyType> vec;
ve // suggestions after <C-X><C-U>:
// "vec v vector<MyType> vec" v is for variable
// "vector p vector<Typename _Tp>" p is for pattern (template)
// constructors with its parameters, etc.
vec. // auto-fired suggestions: all std::vector methods
vec[0]. // auto-fired suggestions: "asdf", "qwer" and MyType methods
return 0;
}
If those examples don't work for you, you haven't installed the plugin properly.
By the way, you can map <C-X><C-U> to other shortcut.

cuda header files

I have a file named "KernelUtil.cu" as follows
__device__ int add(int a, int b)
{
return a+b;
}
I have my main program which is "main.cu". I need to call the "add" function from here. How can I do it?? The following doesnt work.
#include "KernelUtil.cu"
__global__ void test()
{
int c = add(10,10);
}
int main()
{
test<<<1,1>>>();
}
giving an error add is already defined in main.cu
I expect that you have a rule that automatically compiles all .cu files, meaning KernelUtil.cu is effectively compiled twice, once on its own and once when included in main.cu, and therefore add is duplicated.
Try renaming KernelUtil.cu to KernelUtil.h (or .cuh).

Cannot overload make_uint4 function

I'm trying to overload make_uint4 in the following manner:
namespace A {
namespace B {
inline __host__ __device__ uint4 make_uint4(uint2 a, uint2 b) {
return make_uint4(a.x, a.y, b.x, b.y);
}
}
}
But when I try to compile it, nvcc returns an error:
error: no suitable constructor exists to convert from "unsigned int" to "uint2"
error: no suitable constructor exists to convert from "unsigned int" to "uint2"
error: too many arguments in function call
All these errors point to the "return…" line.
I was able to get a partial repro on VS 2010 and CUDA 4.0 (the compiler built the code OK but Intellisense flagged the error you are seeing). Try the following:
#include "vector_functions.h"
inline __host__ __device__ uint4 make_uint4(uint2 a, uint2 b)
{
return ::make_uint4(a.x, a.y, b.x, b.y);
}
This fixed it for me.
I have no problem compiling it in Visual Studio+nvcc. What compiler are you using?
If that would be of any help: make_uint4 is defined in vector_functions.h, line 170 as
static __inline__ __host__ __device__ uint4 make_uint4(unsigned int x, unsigned int y, unsigned int z, unsigned int w)
{
uint4 t; t.x = x; t.y = y; t.z = z; t.w = w; return t;
}
Update:
I get similar error when I try to overload the function while being inside my custom namespace. Are you certain you are not inside one? If so, try putting :: in front of function call to refer to global scope, i.e:
return ::make_uint4(a.x, a.y, b.x, b.y);
I don't have the library code, but it seems like the compiler doesn't like overloaded device functions (as they are treated just like really fancy inline macros). What is does is shadow (hide) the old make_uint4(a,b,c,d) with your new make_uint4(va, vb) and try to call the latter with 4 uint parameters. That doesn't work because there is no conversion from uint to uint2 (as indicated by the first two error messages) and there are 4 instead of 2 arguments (the last error message).
Use a slightly different function name like make_uint4_from_uint2s and you'll be fine.