передача ссылки на структуру из кода ac # для вызова функции DLL c ++, которая принимает ссылку на структуру в своем прототипе - PullRequest
2 голосов
/ 23 марта 2011

У меня есть функция в c ++ DLL, которая имеет следующий прототип

int function(RefPar &params);

как я могу вызвать эту функцию из программы на c #, используя "DLLImport".

когда я попробовал, как показано ниже, AccessViolationException произошло во время работы в visual studio 2008 ..

[DllImport("VistaGMMDLL.dll", EntryPoint = "function"]
unsafe static extern int function(ref RefPar params);

и называется как ..

int ret=function(ref params);

Примечание : структура RefPar имеет много целочисленные значения без знака и 1 перечисление значение в качестве его членов.

Просьба кто-нибудь помочь мне правильно вызвать функцию ..

Ответы [ 3 ]

0 голосов
/ 23 марта 2011

Пара вещей прыгает на меня.Прежде всего, я не понимаю, почему вы должны использовать небезопасно.Во-вторых, вы, вероятно, несоответствие соглашения о вызовах, cdecl в C ++ и stdcall в C #.

Я бы сделал это так:

C ++

struct RESOURCE_PARAMETERS{
    unsigned int uSurfaceHeight;
    unsigned int uSurfaceDepth;
    unsigned int uSurfaceWidth;
    unsigned int uMSAAHeight;
    unsigned int uMSAAWidth;
    unsigned int uArraySize;
    unsigned int uNumSamples;
    unsigned int uMaxLod;
    unsigned int uBpp;
    unsigned int uprefFlag;
    unsigned int uusageFlag;
    RESOURCE_TYPE_REC ResourceType;
    int ResourceFormat;
    int iBuildNumber;
};

int function(RefPar &parameters)
{
}

C #

[StructLayout(LayoutKind.Sequential)]
public struct RESOURCE_PARAMETERS
{
    uint uSurfaceHeight;
    uint uSurfaceDepth;
    uint uSurfaceWidth;
    uint uMSAAHeight;
    uint uMSAAWidth;
    uint uArraySize;
    uint uNumSamples;
    uint uMaxLod;
    uint uBpp;
    uint uprefFlag;
    uint uusageFlag;
    [MarshalAs(UnmanagedType.U4)]
    ResourceType ResourceType;
    int ResourceFormat;
    int iBuildNumber;
} 

[DllImport("VistaGMMDLL.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int function(ref RESOURCE_PARAMETERS parameters);

RESOURCE_PARAMETERS parameters = new RESOURCE_PARAMETERS();
int result = function(ref parameters);

Я не уверен, насколько велико значение enum для размера C ++.Вот почему я поместил явный MarshalAs в код C #.Если это всего лишь один байт, используйте вместо этого UnmanagedType.U1.Я верю, что вы поняли.

Если ваша функция C ++ рассматривает свой параметр как параметр in / out, то использование ref на стороне C # является правильным.Если это действительно выходной параметр, измените код следующим образом:

[DllImport("VistaGMMDLL.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int function(out RESOURCE_PARAMETERS parameters);

RESOURCE_PARAMETERS parameters;
int result = function(out parameters);
0 голосов
/ 24 марта 2011

Еще один очень простой способ вызова этой функции:

Create a c++ dll warapper that link your original dll and contains this function

//c++ code

function2(uint param1, uint param2.....)
{
  RefPar refpar;

  refpar.param1=param1

  refpar.param2=param2

  function(&refpar)

}



in this way you have just to import (in C#) the dll wrapper function in this way


[DllImport("wrapperdll.dll", EntryPoint = "function2"]
static extern int function2(Uint32 param1,Uint32 param2....);


that is very simple to call.


Regards
0 голосов
/ 23 марта 2011

Попробуйте следующим образом:

[StructLayout(LayoutKind.Sequential)]
public struct RefPar
{
    UInt32 uint1;
    UInt32 unti2;
    ....
} 


[DllImport("VistaGMMDLL.dll", EntryPoint = "function"]
unsafe static extern int function(IntPtr params);

//calling

//fill the refParStructure
//create the IntPtr  

refParStruct rs = new RefPar();

IntPtr refparPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(refPar)));


Marshal.StructureToPtr(refParStruct, refparPtr,false);
ret=function(refParPtr);

Дайте мне знать, если вам нужно больше деталей

...