Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with parameters #166

Closed
robigit opened this issue Jul 10, 2020 · 3 comments
Closed

Problem with parameters #166

robigit opened this issue Jul 10, 2020 · 3 comments
Labels

Comments

@robigit
Copy link

robigit commented Jul 10, 2020

From a c++ program I want call some functions of an interface into a managed class library in c#. The call works but I got an exception when the caller exit from the function and it happens only if and when the called function has a parameter. I think this is related to the calling convention stdcall, but I can't figure out how to correctly configure the interfaces. May you give me an hint? Thank you

This is the calling c++ part

Interface

struct INavig : IUnknown
{
   virtual int  __stdcall  CreateNavig   ( int p ) = 0;
   virtual int  __stdcall  CreateNavig2  ( ) = 0;

This is the call

            INavig *prm;
            hPromo = LoadLibrary(L"Managed.dll");
            FARPROC proc = GetProcAddress(hPromo, "get_InstanceByName");
            typedef void(__stdcall* f)(void** I);
            ((f)proc)((void**)(&prm));
             if(prm!=NULL)
             {
                prm->CreateNavig(0);   // ERROR   <----
                prm->CreateNavig2();   // NO ERROR
              }
             FreeLibrary(hPromo);

This is how it is implemented in c #

DllExport

     public static class Exports
    {
        [DllExport (ExportName = "get_InstanceByName" ) ]
        public static void get_InstanceByName(  [MarshalAs(UnmanagedType.Interface)]out ItfNavig instance)
        {
                instance = new ImplItfNavig();
        }
    }

The Interface

    [Guid("546e25c7-59b2-4d58-ac72-442293da4753"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface ItfNavig
    {
        int CreateNavig(int p);
        int CreateNavig2();

and the implementation

    public class ImplItfNavig : ItfNavig
    {
        public int CreateNavig(int p)
        {
            return 1;
        }
        public int CreateNavig2()
        {
            return 2;
        }
@3F
Copy link
Owner

3F commented Jul 10, 2020

@robigit

I'm not sure what are you trying, but, I'm watching IUnknown interface in your src. Is there any reason why not to make it initially as COM visible component if you've plan to use this anyway? Or try this if you just need complex types etc.

I think this is related to the calling convention stdcall

In any case, our tool is configured for __cdecl by default [?]

@robigit
Copy link
Author

robigit commented Jul 13, 2020

Thank you for your answer. What I'd want to do i substitute an old c++ dll, that exports the ItfNavig I put in the example (not INavig, that was a typo cleaning the code) with a new c# managed dll.
However I discovered that in c# there is an automatic signature conversion of the methods of the com interfaces. Infact they should always export an HRESULT. So if in c# you write

int CreateNavig(int p);

in c++ it should become

HRESULT CreateNavig (int *result, int p)

But this is not my case and the reason of the exception.

As I can't change the c++ interface, to solve it has been sufficient tell to c# to not change the signature, so in c# the method changes in

[PreserveSig]
int CreateNavig(int p);

And all worked fine.

I hope this can be useful to someone else

@3F
Copy link
Owner

3F commented Jul 14, 2020

All correct. We need to use PreserveSig to avoid mentioned transformation in COM interop.

Otherwise you can also try with some offset to the specific field like ~ prm->CreateNavig(0, &result)

Moreover, in past, I already voiced about hack with offsets for IUnknown 3F/Conari#8 when raw access to data 3F/Conari#2 (comment)

That can be considered in the manner of Conari: https://github.com/3F/Examples/blob/master/DllExport/BasicExport/UnmanagedCppConsole/UnmanagedCppConsole.cpp#L59 and so on

I hope this can be useful to someone else

Yes! Thank you for the tips in our Q&A list.

@3F 3F closed this as completed Jul 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants