Link to home
Start Free TrialLog in
Avatar of roverm
rovermFlag for Netherlands

asked on

Call C++ from C#

Hi all,

I am implementing a C++ dll into my C# application. My knowledge of C++ is very basic so I don't know how to translate some structs and events.

The biggest problem I have right now is how to hook up events. C++ needs the following struct as input on a method:

typedef struct
{
  HWND parent;
... (others)
  EXT_FUNCTIONS  externalFunctions;

  void (__stdcall *fFirstCaller)        (void *pVoidExternal, int Parms);
  void (__stdcall *fSecondCaller)    (void *pVoidExternal);
} PARAMETERS

typedef struct EXT_FUNCTIONS_TYPE
{
  int    (__stdcall *FirstEvent)    (void* pVoidExternal);
  void  (__stdcall *Executing)     (void* lpVoid1, int Parm1, int Parm2, unsigned char *szParm3);
}  EXT_FUNCTIONS

Open in new window


I a using DLLImport to load the DLL into memory in C# and use "external static" to get a reference to the functions.
If I understand correct both above structs also need eventhandler. How must I translate and use the structs in C#?

Please supply examples.
Avatar of jkr
jkr
Flag of Germany image

I am sorry, but if a native code DLL requires callback function pointers, you won't be able to supply them from managed code for it's sheer nature. They have to be be implemented in native code as well.
Avatar of roverm

ASKER

What do you mean?
There is no such thing as function pointers in managed code. Therefore, you will have to wrap another layere of native code around the DLL you want to use and call that layer from C#. Function pointers are direct offsets into native assembly code (OK, that's a bit simplified, yet on the head), that's why they have no counterparts in the managed world.
ASKER CERTIFIED SOLUTION
Avatar of ambience
ambience
Flag of Pakistan image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
As an example, see the following C++/CLI snippet from a real project with native and managed code mixed.

IComponentHost^ SomeComponentHostFactory::CreateComponentHost(List<KeyValue^>^ config)
{
	auto dictionary = ConfigHelper::ToDictionary(config);
	ConfigHelper::Require(dictionary, L"BaseFolder");
	ConfigHelper::Require(dictionary, L"Arguments");

	std::auto_ptr<Native::SomeComponentHostConfig> cfg = new Native::SomeComponentHostConfig();

	cfg->friendlyName = "SomeComponent";
	cfg->workingDir = marshal_as<std::string>( dictionary[L"BaseFolder"] );
	cfg->arguments = marshal_as<std::string>( dictionary[L"Arguments"] );
	cfg->filePath = PathUtil::combine(cfg->workingDir.c_str(), "SomeComponent.exe" );

	cfg->visibility = SW_NORMAL;
	cfg->useNewConsole = false;
	cfg->captureOutput = false;
	cfg->priorityClass = NORMAL_PRIORITY_CLASS;
	cfg->joinTimeout = 3 * 60 * 1000;
	cfg->severity = SEVERITY_CRITICAL;
	cfg->allowAttach = true;

	if(dictionary->ContainsKey(L"CoredumpEnabled"))
	{
		cfg->coredump = System::Convert::ToBoolean( dictionary[L"CoredumpEnabled"] );
	}
	if(cfg->coredump)
	{
		std::string dumpFolder = dictionary->ContainsKey(L"CoredumpFolder") ? marshal_as<std::string>( dictionary["CoredumpFolder"] ):"app://";
		cfg->coredumpLevel = Sys::Diagnostic::CoreDumpWriter::Full;
		cfg->coredumpFolder = PathUtil::resolve( dumpFolder.c_str() );
	}

	auto service = gcnew SomeComponentNativeHostWrapper(cfg.detach());
	return service;
}

Open in new window

Avatar of roverm

ASKER

@jkr: "There is no such thing as function pointers in managed code.". As far as I know you can create a delegate (Delegate.Create method) and get it's pointer using MarshalAs.GetFunctionPointer...

@ambience: Yes, I saw C++/CLI before but this is completely new to me. Do you know any good and quick tutorial?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of roverm

ASKER

Hi minhvc,

Thanks for your comments, I will look into it.
Avatar of roverm

ASKER

Hi all,
I am closing this Q. The problem was not solved but I am sure your methods would do the trick.
Thanks for your efforts.

RoverM