jensa
jensa

Reputation: 2890

Passing integers from VB.Net to C++ dll

I have a problem which I just can't figure out. I'm trying to call a member function of a C++ class from VB.Net by using a wrapper function, and passing a pointer to this wrapper function.

C++:

class _declspec(dllexport) MyClass{
public:
    int multiply(int x, int y) const;
    char* get_name() const;
};

_declspec(dllexport) void* createMyClass();
_declspec(dllexport) void destroyMyClass(void* objptr);
_declspec(dllexport) int MyClass_multiply(void* objptr, int x, int y);

The definitions are:

int MyClass::multiply(int x, int y) const
{
    return x * y;
}

char* MyClass::get_name() const
{
    return "jensa";
}

void* createMyClass()
{
    return new MyClass;
}

void destroyMyClass(void* objptr)
{
    delete static_cast<MyClass*>(objptr);
}

int MyClass_multiply(void* objptr, int x, int y)
{
    std::ofstream fout("jojo.txt", std::ios::out);
    fout << x << std::endl;
    fout << y << std::endl;
    MyClass* p = (MyClass*)(objptr); // Explicit type cast
    fout << p->get_name() << std::endl;
    fout.close();
    return p->multiply(x,y);
}

I use the ofstream just for checking what the arguments actually are inside the C++ function MyClass_multiply. If I call the function from VB.Net like this

<DllImport(Constants.DLL_PATH, EntryPoint:="MyClass_multiply",  CallingConvention:=CallingConvention.Cdecl)>
Private Shared Function MyClass_multiply(ByVal objptr As Long, ByVal x As Long, ByVal y As Long) As Long
End Function

Dim objptr As Long = createMyClass()
Me.TextBox3.Text = MyClass_multiply(objptr, 2, 3)

I find that the first integer argument in the C++ function MyClass_multiply, x, becomes some strange value like 63203420, and the argument y takes on the value which x was set to. When I created a similar function add in my C++ dll, which only took two integers and no void*, everything worked fine. Am I doing something wrong with the void*? (Note: I'm using http://www.codeproject.com/Articles/6244/Step-by-Step-Calling-C-DLLs-from-VC-and-VB-Part).

Thank you!

Edit: I am using a .def file.

LIBRARY MyLib.dll
EXPORTS
    add
    createMyClass
    destroyMyClass
    MyClass_multiply

Upvotes: 0

Views: 973

Answers (2)

jensa
jensa

Reputation: 2890

It seems to be working now. I changed all occurences of

objptr As Long

to

objPtr As IntPtr

per your suggestion. I also noticed that I needed all the other variables (x and y in the MyClass_multiply function) to be of type Integer, NOT Long). That is,

<DllImport(Constants.DLL_PATH, EntryPoint:="MyClass_multiply", CallingConvention:=CallingConvention.Cdecl)>
Private Shared Function MyClass_multiply(ByVal objptr As IntPtr, ByVal x As Integer, ByVal y As Integer) As Integer
End Function

Just to be clear: Just as you suggested I needed to make ALL other types Integers. Having function arguments as Integer and the return value Long did not work. Having Long function arguments but Integer return value did not work either. Hopefully this could help others in a similar situation! Thanks!

Upvotes: 0

qwr
qwr

Reputation: 3670

Private Shared Function MyClass_multiply(ByVal objptr As IntPtr, ByVal x As Integer, ByVal y As Integer) As Integer
End Function

If you have many codes of native that should be p/invoked you can try tool. It generaes for both c# and VB.Net

making Pinvoke easy

Upvotes: 1

Related Questions