Related
I'm trying to create a DLL using Visual C++ that is called from a Delphi 5 program. The Delphi program passes in a record, which is then edited in the DLL, and the Delphi program uses the results.
For example, the Delphi code is similar to the following:
Type dll_btvar = record
age : smallint;
name : array[0..11] of char;
value : Double;
end;
// Import the function from the dll
function foo(CVars : dll_btvar):integer; external 'example.dll';
// Call the dll
function callFoo(var passedVar:dll_btvar):integer;
begin
result := foo(passedVar);
// Use passedVar.value
end;
A sample of the C++ code:
In example.h:
#pragma once
#include "dllVar.h"
extern "C" {
__declspec(dllexport) int foo(DLL_Var var);
}
In example.cpp:
#include "example.h"
int foo(DLL_Var var){
var.value = var.age + var.name[0];
return 0;
}
In dllVar.h:
#pragma once
#pragma pack(8)
extern "C" {
struct DLL_Var {
short age;
char name[12];
double value;
}
}
I use #pragma pack(8) as that value gave correct alignment so that the passed record is read correctly in the DLL.
In the sample code, when passing an age and name, I expect value to be set by the DLL, which can then be recovered in the Delphi program. Result would be some sort of error code.
Using identical code in C++ Builder 5 did work, however it is of course outdated and I haven't moved all the code in my DLL over (nor do I want to), only the minimum you see here.
I tested a couple of ways to have Delphi pass an address/pointer to the dll, however they didn't change anything.
Right now, the return value is sent correctly, but the fields of the record (i.e. value) remain unchanged.
What changes do I need to make to either the Delphi or C++ to capture changes in the passed record? I am happy to work extensively with the C++ but I'd prefer to keep the Delphi changes to a minimum since this is old software that I don't want to break.
function foo(CVars : dll_btvar):integer; external 'example.dll';
The problem starts here, in the Delphi code. The record is passed by value. That is, the caller's record variable is copied to a new variable which is then passed to the function. This means that modifications by the callee to this copy of the record are not seen by the caller. You must therefore pass the parameter as a var parameter:
function foo(var CVars : dll_btvar):integer; external 'example.dll';
The next problem is the calling convention. You must use the same calling convention for both sides. Your code uses the default register convention on the Delphi side, which is not supported by non-Borland/Embarcadero tools. Use stdcall or cdecl instead. Let's opt for cdecl, the default for most C++ tools:
function foo(var CVars : dll_btvar):integer; cdecl; external 'example.dll';
To make the C++ code match, pass the argument by reference:
__declspec(dllexport) int __cdecl foo(DLL_Var &var);
Or explicitly use a pointer:
__declspec(dllexport) int __cdecl foo(DLL_Var *var);
In the latter option, the implementation needs to be changed because of the use of a pointer:
int foo(DLL_Var *var){
var->value = var->age + var->name[0];
return 0;
}
Using identical code in C++ Builder 5 did work.
No it did not, because the Delphi code in your question cannot modify the caller's record.
I have an existing Win32 C++ DLL, which needs to be accessed by a VB6 client. One of the exported functions is defined as follows:
__declspec(dllexport) long __stdcall Foo(long nId, LPCWSTR pszwPath = nullptr);
Unfortunately, VB6 always converts strings to ANSI when calling DLL functions via a Declare statement. In order to bypass this limitation, I have embedded a type library, which features the following signature for the function:
[uuid(...)]
library FooLib
{
[
helpstring("FooLib"),
dllname("Foo.dll")
]
module FooMdl
{
[entry("Foo")]
long __stdcall Foo([in] long nId, [in,unique,string,defaultvalue(0)] LPCWSTR pszwPath);
}
};
This won't compile however, as MIDL generates the following error:
error MIDL2020 : error generating type library : AddFuncDesc failed : Foo
My next attempt involved utilizing the optional attribute:
long __stdcall Foo([in] long nId, [in,unique,string,optional] LPCWSTR pszwPath);
While this type library can be compiled successfully, the VB6 client crashes with an access violation as soon as the optional string value is omitted.
I am aware that I could change the LPCWSTR argument to a BSTR type, thereby remedying the problem. However, this would also require me to change the signature and implementation of the existing DLL.
Is it therefore possible to define a char / wchar_t pointer argument as optional or with a NULL default value? Or am I simply out of luck here?
I am told to import my writen class in C++ into a dll and then use that dll in a c# application. Following this guide I created the dll, but I can't simply use it in a C# application since there are some issues concerning it:
What should I place for the return type of my factory function?
What is the equivalent of const wchar_t* which is my constructors argument type?
How can I retrieve and use my functions return type which is of type vector< wstring>?
These are the problems that prevent me from using my C++ DLL inside my C# applications. I was told that I need to create a wrapper with C++/CLI and then use that inside my C#. But sadly I have no idea about it, I don't know C++.net.
The only thing that currently seems to be a bit more sensational to me is to make it somehow compatible with C and then create a C DLL and use that in my C# application. I have read that in C, class object pointers are accessible through HANDLEs, so I thought that would be good idea to get things going without a lot of changes.
So the question is how can I use Handles to access my class objects in C and use them? And how can I convert a vector<wstring> to its C counterpart?
If I want to use CLI to create a wrapper (DLL?) for my C++ DLL, to be used in other dotnet apps what should I do?
In order to make a C wrapper for a C++ class to be used in for example a C# application you can do the following.
In Visual Studio choose Win32 Console Application and Enter a name, Then click next and on the next pane choose DLL and click finish. When you are done you are represented with a DLL project including 3 files.
testdll.h
testdll.cpp
dllmain
Delete everything that exists inside your testdll.h and testdll.cpp files and copy the following contents to each respectively. Add these lines to your testdll.h
// Our C wrapper for creating a dll to be used in C# apps
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the TESTDLL_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// TESTDLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef TESTDLL_EXPORTS
#define TESTDLL_API __declspec(dllexport)
#else
#define TESTDLL_API __declspec(dllimport)
#endif
extern "C"
{
TESTDLL_API int OurTestFunction(int x, int y);
}
It is inside this extern "C" block where you define your interface, functions to access your class member functions.Note the TESTDLL before the function prototype. All of your functions must be proceeded by that.
Add these to your testdll.cpp file:
#include "testdll.h"
#include "ourClass.h"
#define DLL_EXPORT
extern "C"
{
OurClass ourObject;
TESTDLL_API int OurTestFunction(int x, int y)
{
return ourObject.Add(x,y);
}
}
You compile this and get a C based dll which can be used in a C# application.
There are couple of things to notice though, The more important ones are:
You need to understand that the code you use as a proxy- i mean
function definition inside your testdll.h, must only use C
compatible types, it is C after all not C++.
is that you would want to be able to allocate new objects of your
class instead of just using one global object to access all methods.
For this, if you need to pass your class objects between member functions, you need to first convert it to a void* which C can understand and then pass it and use it to access your member functions of whatever.
For example I would have something like this inside my testdll.h in order to make user capable of managing the objects indirectly:
#ifdef TESTDLL_EXPORTS
#define TESTDLL_API __declspec(dllexport)
#else
#define TESTDLL_API __declspec(dllimport)
#endif
extern "C"
{
TESTDLL_API int OurTestFunction(int x, int y);
TESTDLL_API void* CreateHandle();
TESTDLL_API void* GetCurrentHandle();
TESTDLL_API void DisposeCurrentHandle();
TESTDLL_API void SetCurrentHandle(void* handle);
TESTDLL_API void* GetHandle();
TESTDLL_API void DisposeHandle(void*);
TESTDLL_API void DisposeArrayBuffers(void);
}
And inside my testdll.cpp I would define them as :
#include "testdll.h"
#include "ourClass.h"
#define DLL_EXPORT
extern "C"
{
OurClass *ourObject;
TESTDLL_API int OurTestFunction(int x, int y)
{
//return ourObject.Add(x,y); -- not any more !!
ourObject = reinterpret_cast<OurClass *>(GetHandle());
}
//Handle operations
TESTDLL_API void* CreateHandle()
{
if (ourObject == nullptr)
{
ourObject = new OurClass ;
}
else
{
delete ourObject ;
ourObject = new OurClass ;
}
return reinterpret_cast<void*>(ourObject);
}
TESTDLL_API void* GetCurrentHandle()
{
return reinterpret_cast<void*>(ourObject );
}
TESTDLL_API void DisposeCurrentHandle()
{
delete ourObject ;
ourObject = nullptr;
}
TESTDLL_API void SetCurrentHandle(void* handle)
{
if (handle != nullptr)
{
ourObject = reinterpret_cast<OurClass *>(handle);
}
else
{
ourObject = new OurClass ;
}
}
//factory utility function
TESTDLL_API void* GetHandle()
{
void* handle = GetCurrentHandle();
if (handle != nullptr)
{
return handle;
}
else
{
ourObject = new OurClass ;
handle = reinterpret_cast <void*>(ourObject );
}
return handle;
}
CDLL_API void DisposeHandle(void* handle)
{
OurClass * tmp = reinterpret_cast<OurClass *>(handle);
delete tmp;
}
TESTDLL_API void DisposeArrayBuffers(void)
{
ourObject = reinterpret_cast<OurClass *>(GetHandle());
return ourObject ->DisposeBuffers();//This is a member function defined solely for this purpose of being used inside this wrapper to delete any allocated resources by our class object.
}
}
And when we compile this Dll, we can easily work with it inside our C# application. Before being able to use our functions defined in this dll we need to use appropriate [ImportDll()]. So for our TestDll we would write:
[DllImport(#"TestDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int OurTestFunction(int firstNumber,int secondNumber);
And finally use it like:
private void btnReadBigram_Click(object sender, EventArgs e)
{
int x = OurTestFunction(10,50);
MessageBox.Show(x.ToString());
}
This is all I did to make my C++ class member functions accessible inside a C# application without any hassle.
Note:
When compiling your C# application make sure you have chosen the x86 Platform for compiling your project not AnyCpu.You can change your platform through properties.
Note 2:
For knowing how to create a C++/CLI wrapper for your native C++ class read this: C++/CLI wrapper for your native C++ class.
Using a native C++ class directly from C# is technically possible, but it's not trivial, and it's rarely even a good idea. For starters, you have to know the names to use to import from the DLL, which will be the names after C++ name-mangling. You also can't directly access things like vector from C#.
There are basically two good options:
The first is to write a DLL with a C interface that uses only types that can be marshalled into CLR types. You may use pointers along with the IntPtr type, but you can't really dereference those pointers. You can pretty much just store them in your C# code and then pass them back to the native DLL when needed. And you can also use simple struct types as long as you don't need deep copy to work on them. This option involves using P/Invoke.
The second option is to write a mixed-mode C++/CLI assembly that implements all the logic that needs to access your native code. This assembly can directly access classes and data from your C# code and also directly access your native code, although you should be forewarned that there are annoying breaks where you can't mix the two. For example, a ref class in C++/CLI can't have a shared_ptr member. However, it can have a raw C++ pointer as a member. A (mixed-mode) native class can also have access to a CLR handle type and make calls into the C# code through this. This option involves using C++ Interop.
It's worth noting that you could also go the other way with C++ Interop. You could have your C# code access a mixed-mode C++/CLI assembly that provides a .NET interface to some native code. However, you will still have to do some translation in this case so it's not hugely better than the first option.
A full tutorial on C++ Interop would be rather lengthy. I suggest you read up here and do some further investigation of C++ Interop on Google.
C++/CLI introduces managed objects, for which the pointer token * should be replaced with a ^, and a 'new' should be replaced with 'gcnew', you don't need to delete these objects when you're done with them, they'll be garbage collected, [edit] managed classes have a ref keyword in their definition [/edit].
Wrapping the C++ MyClass class in a C++/CLI wrapper class WrapperCLass could look something like this:
#include <stdio.h>
class MyClass
{
public:
void ShowStuff(const wchar_t *a)
{
wprintf(a);
}
};
public ref class WrapperClass
{
MyClass *wrapped;
public:
WrapperClass()
{
wrapped = new MyClass;
}
~WrapperClass()
{
delete wrapped;
}
void ShowStuff(IntPtr string)
{
wrapped->ShowStuff((const wchar_t *)string.ToPointer());
}
};
If you generate a dll with this, you'll be able to use it as a reference in your C# project
and you won't have to use the factory function mechanism.
In C++/CLI are available, so const wchar_t * is as wel.
To convert a System::String to a const wchar_t * you could use something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client
{
class Program
{
static void Main(string[] args)
{
WrapperClass w = new WrapperClass();
IntPtr tmp;
w.ShowStuff(tmp = System.Runtime.InteropServices.Marshal.StringToHGlobalUni("Test"));
System.Runtime.InteropServices.Marshal.FreeHGlobal(tmp);
}
}
}
(There could very well be better ways to do this...)
For your return type you'll have to do the conversion in your wrapper class. Make some .net collection, iterate through your vector, convert the wstring to a System::String, and add it to the .net collection, and return that.
I am using c++ library in my objective c project.
I integrated c++ library and implemented .mm file to bridge c++ and objective c.
I can successfully call c++ function from my objective c using this .mm bridge.
The issue is that methods in given c++ library return's nothing i.e Void.
For example void login( const char* email, const char* password);
This c++ library have call back function implemented to know the result of this login method.
Example:
class DemoApp : public XClass
{
int urandomfd;
public:
uint32_t dstime(void);
FileAccess* newfile();
void request_error(MegaClient*, error);
void login_result(MegaClient*, error);
void users_updated(MegaClient*, User**, int);
void nodes_updated(MegaClient*, Node**, int);
int prepare_download(MegaClient*, Node*);
void share_result(MegaClient*, int, error);
void account_details(MegaClient*, AccountDetails*, int, int, int, int, int, int);
void topen_result(MegaClient*, int, error);
void topen_result(MegaClient*, int, string*, const char*, int);
void transfer_update(MegaClient*, int, off_t, off_t, uint32_t);
void transfer_error(MegaClient*, int, int, int);
void transfer_failed(MegaClient*, int, error);
void transfer_failed(MegaClient*, int, string&, error);
void transfer_limit(MegaClient*, int);
void transfer_complete(MegaClient*, int, chunkmac_map*, const char*);
void transfer_complete(MegaClient*, int, const byte*, const byte*, SymmCipher*);
void changepw_result(MegaClient*, error);
void reload(MegaClient*, const char*);
void notify_retry(MegaClient*, int);
void debug_log(MegaClient*, const char*);
DemoApp();
};
So now my concern is how and when should i call these CALLBACK function's in my objective C library, which look's to me that they are called internally in c++ library.
This is my wrapper.mm file, wrapping c++ methods, need to call in objective c.
-(void) WrapLogin:(NSString*) email :(NSString*) pwd{
self.wrappedModelAccessMega->Login([email UTF8String], [pwd UTF8String]);
//No return as Login mfunction from c++ library returns nothing i.e void
}
I am working on it from a while and already pushed hard to integrate this library to my objective C library now i got stuck to it due to these callback function's.
Please small example showing how should i use callback function of c++, wrap it and call in my objective c to get/know result/return of my login function will do the great job for me.
The Simple answer is:
logic behind writing callback function is that they should get call
internally when response comes from server or certain event happens.
If you want to use this, you need to implement logic let say store
value in variable and return this variable after this callback
function get called. (Not Recommended)
If you want to use this callback function in other platform let say
objective C then bridge this callback function with Delegates. (Recommended)
Thanks to Mr Jaggu who helped me in knowing this.
I'm trying to port a Windows app to Linux. This appplication marks some functions with the __stdcall attribute. However, I was told by a friend that stdcall is used only on Windows and has no meaning in Linux (but DOES exist in Windows GCC).
Searching Google - some results state that there IS stdcall in Linux.
Is there a stdcall in Linux?
Additionally, GCC indicates that:
__attribute__((__stdcall__)) and __attribute__((stdcall)) (without the underscores near stdcall).
Which one is preferred (if applied to Linux at all)?
The simplest solution is to just define __stdcall to nothing conditionally on Linux.
Here's a link to __stdcall description on MSDN:
http://msdn.microsoft.com/en-us/library/zxk0tw93(VS.80).aspx
It's only used to call WinAPI functions. To port such a Windows application to Linux, you need much more than just defining __stdcall to nothing:
#ifndef WIN32 // or something like that...
#define __stdcall
#endif
You would also need to call the Linux-specific API functions instead of Win32 API ones. Depending on the particular part of Win32 API and the size of the application (amount of code), it can be anywhere between moderately difficult and daunting.
Which specific functions are marked by the app as __stdcall?
Indeed, Windows port of GCC has to have __stdcall, because it's supposed to be able to generate conforming code for the Win32 platform. But since under Linux there is only one standard calling convention and it coincides with the default compiler output, this statement is not needed.
The reason your application is not compiling under Linux is almost certainly due to the fact, that it references Win32 API functions that are not defined under Linux -- you need to find appropriate Linux counterparts. Win32 API and Linux GLibc API-s are very much different and cannot be substituted easily.
Probably the easiest way to port your app to Linux would be to use Wine, i.e. modifying the Windows code in such a way, that it runs smoothly under Wine in Linux. This is the way even the most complex applications, like modern computer games, have been made to run under Linux.
Of course, if you really want it to be running natively under Linux, then porting is the only way to go.
stdcall is NOT just a calling convention; in addition to being a calling convention, it allows an isomorphism between C and C++ objects. Here's an example:
#define _CRT_SECURE_NO_WARNINGS // disable marking use of strcpy as error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
class ICdeclGreeter {
public:
virtual ~ICdeclGreeter(){}
virtual void setGreeting(const char *greeting) = 0;
virtual void greet() = 0;
};
class IStdcallGreeter {
public:
virtual __stdcall ~IStdcallGreeter(){}
virtual void __stdcall setGreeting(const char *greeting) = 0;
virtual void __stdcall greet() = 0;
};
class CdeclGreeter : public ICdeclGreeter {
public:
char *greeting;
~CdeclGreeter() {
if (greeting != nullptr) {
free(greeting);
puts("[CdeclGreeter] destroyed");
}
}
void setGreeting(const char *greeting) {
this->greeting = (char *)malloc(strlen(greeting) + 1);
strcpy(this->greeting, greeting);
}
void greet() {
puts(greeting);
}
};
class StdcallGreeter : public IStdcallGreeter {
public:
char *greeting;
__stdcall ~StdcallGreeter() {
if (greeting != nullptr) {
free(greeting);
puts("[StdcallGreeter] destroyed");
}
}
void __stdcall setGreeting(const char *greeting) {
this->greeting = (char *)malloc(strlen(greeting) + 1);
strcpy(this->greeting, greeting);
}
void __stdcall greet() {
puts(greeting);
}
};
typedef struct pureC_StdcallGreeter pureC_StdcallGreeter;
typedef struct pureC_StdcallGreeterVtbl {
void (__stdcall *dtor)(pureC_StdcallGreeter *This);
void (__stdcall *setGreeting)(pureC_StdcallGreeter *This, const char *greeting);
void (__stdcall *greet)(pureC_StdcallGreeter *This);
} pureC_IStdcallGreeterVtbl;
struct pureC_StdcallGreeter {
pureC_IStdcallGreeterVtbl *lpVtbl;
char *greeting;
int length;
};
/* naive attempt at porting a c++ class to C;
on x86, thiscall passes This via ecx register rather than
first argument; this register cannot be accessed in C without
inline assembly or calling a reinterpretation of byte array
as a function. there is no "This" argument in any of below. */
typedef struct pureC_CdeclGreeter pureC_CdeclGreeter;
typedef struct pureC_CdeclGreeterVtbl {
void (*dtor)(pureC_CdeclGreeter *This);
void (*setGreeting)(pureC_CdeclGreeter *This, const char *greeting);
void (*greet)(pureC_CdeclGreeter *This);
} pureC_CdeclGreeterVtbl;
struct pureC_CdeclGreeter {
pureC_CdeclGreeterVtbl *lpVtbl;
char *greeting;
int length;
};
void test() {
ICdeclGreeter *g = new CdeclGreeter;
g->setGreeting("hi");
g->greet();
IStdcallGreeter *g2 = new StdcallGreeter;
g2->setGreeting("hi");
g2->greet();
// we can pass pointers to our object to pure C using this interface,
// and it can still use it without doing anything to it.
pureC_StdcallGreeter *g3 = (pureC_StdcallGreeter *)g2;
g3->lpVtbl->setGreeting(g3, "hello, world!");
g3->lpVtbl->greet(g3);
g3->lpVtbl->dtor(g3);
free(g2);
/*
// cdecl passes this via ecx in x86, and not as the first argument;
// this means that this argument cannot be accessed in C without
// inline assembly or equivelent. Trying to run code below will cause a runtime error.
pureC_CdeclGreeter *g4 = (pureC_CdeclGreeter *)g;
g4->lpVtbl->setGreeting(g4, "hello, world!");
g4->lpVtbl->greet(g4);
g4->lpVtbl->dtor(g4);
free(g);
*/
delete g;
}
int main(int argc, char **argv)
{
test();
system("pause");
return 0;
}
TLDR; it's not the same as cdecl makes C++ classes not usable from C on platforms using this convention because in order to send "This" to a method, you must set ecx register to address of "This" rather than just pushing it, and likewise if you want to implement a class in C that C++ can recognize, the method will need to get This pointer from ecx register which is not accessible to C without inline assemby or equivelent.
stdcall has this nice property that classes that use stdcall can easily be simultaneously usable from C or C++ without doing anything to them.
So you can only #define __stdcall as long as you don't deal with __thiscall; although there might be some other subtle distinctions.