I want to call the dl function from c# with a structure containing a double pointer variable as an argument.

Asked 2 years ago, Updated 2 years ago, 147 views

It's just as the title says.
I would like to reuse the dll that I created in the past and call it using a structure containing variables of double pointers (the real thing is a char array), but the following exceptions have occurred and it doesn't work.

[Exception]
System.TypeInitializationException: 'PayGwApp.ComTask' type initializer threw an exception.
AccessViolationException—An attempt was made to read or write to protected memory.Other memory may be corrupted.

The structures are as follows:

unsafe structure cmdq{
        public ulong Size;
        public char**ppData;
    }

I want to set the array data in ppData and call the c++ side function, but it doesn't work.

The implementation is as follows:

// Function you want to call
    [DllImport("mycmdq.dll")]
    private external static long cmdq_exec(ushorti_id, IntPtr CmdQ);

    private unsafe void InitData()
    {
        cmdqt_cmdQ = new cmdq();
        t_cmdQ.Size=200;

        try
        {
            char [ ] Data = new char [200];

            // DUMMY FOR TEST
            for (int idx=0; idx<Data.Length;idx++)
            {
                Data [idx] = (char) (idx+1);
            }

            fixed(char*pData=&Data[0])
            {
                t_cmdQ.ppData=&pData;
            }

            IntPtrcmdqPtr=Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ulong))+Marshal.SizeOf(typeof(char))*Data.Length);
            Marshall.StructureToPtr(t_cmdQ,cmdqPtr,false);

            ret = cmdq_exec(20, cmdqPtr);
            Console.WriteLine("sndbuf" + ret.ToString());

            Marshall.FreeCoTaskMem (cmdqPtr);
        }
        catch (Exception exception)
        {
            Console.WriteLine("");
        }
    }

I've tried many things, but I can't solve them.
If you are familiar with it, could you please help me?

c# c++ windows dll

2022-09-30 19:29

2 Answers

There are many problems with the source code listed, so I can point it out, but I can't give you the code to solve it because I don't know what the correct action is being asked for.

fixed suppresses memory movement for a period of time in a statement.Memory movement can occur because it is released when a statement is left out.Therefore, it is wrong to keep the pointer obtained in the fixed statement.

Marshal.AllocHGlobal corresponds to Marshal.FreeHGlobal.Conversely, Marshal.FreeCoTaskMem corresponds to Marshal.AllocCoTaskMem.The response is not correct.

C# ulong is a 64-bit unsigned integer, and C++ corresponds to uint64_t.unsigned long in Windows C++ is defined as 32 bits, so it is not correct if you are expecting this.
Similarly, C# char represents a 16-bit Unicode character.C++ corresponds to char16_t.char in Windows C++ represents an 8-bit ANSI character, so if you're expecting this, it's not correct.


2022-09-30 19:29

In order to get a pinpoint answer to the phenomenon of the question, it would have been faster if you had the structure cmdq definition or the cmdq_exec entry part source.
If you say dll that you made in the past, you should have the source yourself.

For example, if you create a dummy C++ dll in VS2019, the moving version will have this source.It only checks the validity of the call, recovery, and parameter data.
In Unicode mode, both C# and C++ were built in 32 bits.

#include "pch.h"
BOOL APIENTRY DllMain (HMODULE hModule, DWORDul_reason_for_call, LPVOID lpReserved)
{
    return TRUE;
}

typeef structure cmdq {
    ULONGLONG Size;//## If this is ULONG, make C# side uint
    TCHAR**ppData;
};
                                      //## Is the following cmdqptr type pointer cmdq*?
external "C" __declspec(dllexport) long cmdq_exec(USHORT i_id, cmdq*cmdqptr)
{
    TCHAR**ppData=cmdqptr->ppData;
    TCHAR*pData=*ppData;
    for (ULONGLONG i=0;i<cmdqptr->Size;i++)
    {
        TCHAR c=pData[i]; //### This process is meaningless, but if it is in Debug mode, it will be checked.
    }
    return(long)cmdqptr->Size;
}

Check if the above part of C++ dll and the build's Unicode/ANSI mode are correct.I think it's a good idea to make these dummies and check them one by one.

Based on the phrase "System.TypeInitializationException: 'PayGwApp.ComTask' type initializer threw an exception", the above has actually been cleared and the problem may have occurred within the true cmdq_exec.

The only way to investigate this is to incorporate a complete set of dll projects that you created in the past into the C# solution and run them both in debug mode.


2022-09-30 19:29

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.