我的c ++和c#互操作崩溃为64位,为什么?指针大小? [英] my c++ and c# interop crashes in 64 bit, why? pointer size?

查看:84
本文介绍了我的c ++和c#互操作崩溃为64位,为什么?指针大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个本地32位dll(无源),该dll在我使用的应用程序中作为插件运行.我自己完成了另一个本机dll,它将与该插件通信,以便创建和更新该插件的控件. 从该dll中,我导出了我需要的功能,以便通过c#应用程序(使用p/invoke)控制插件.

i got a native 32 bit dll (no source) which runs as a plugin in an application i use. I've done another native dll myself which will communicate with that plugin in order to create and update the plugin's controls. From that dll i've exported the functions I need in order to control the plugin from my c# application (with p/invoke).

这是代码:

h个文件:

#pragma once

#include "include\SpoutControls.h"

extern "C" { __declspec(dllexport) void InitializeControls(char *sendername, int *numControls, char** names, int *types, float* floats, float* toggles, float* press, char** text); }
extern "C" { __declspec(dllexport) bool UpdateControls(const char** text, float *floats, float *toggles, float *press, int *numControls); }
extern "C" { __declspec(dllexport) void CloseControls(); }
//
extern "C" __declspec(dllexport) int ReleaseMemory(float *pArray)
{
    delete[] pArray;
    //delete[] Usize;
    return 0;
};

cpp:

#include "SpoutControls4vvvv.h"

//SpoutControls and the functions
//CreateControl, OpenControls, CheckControls, CloseControls
//are declared in SpoutControls.h, which comes with the 32 bit plugin dll
SpoutControls spoutcontrols;

void InitializeControls(char *sendername, int *numControls, char** names, int *types, float* floats, float* toggles, float* press, char** text) {

    int Vcontrols = numControls[0];
    int Tcontrols = numControls[1];
    int Pcontrols = numControls[2];
    int Scontrols = numControls[3];

    int all = Vcontrols + Tcontrols + Pcontrols + Scontrols;
    int v=0, t=0, p=0, s = 0;

    for (int controlID = 0; controlID < all; controlID++) {

        if (types[controlID] == 0) {
            spoutcontrols.CreateControl(names[controlID], "float",0.0,1.0, floats[v]);
            v++;
        }
        if (types[controlID] == 1) {
            spoutcontrols.CreateControl(names[controlID], "bool", toggles[t]);
            t++;
        }
        if (types[controlID] == 2) {
            spoutcontrols.CreateControl(names[controlID], "event", press[p]);
            p++;
        }
        if (types[controlID] == 3) {
            spoutcontrols.CreateControl(names[controlID], "text", text[s]);
            s++;
        }

    }

    spoutcontrols.OpenControls(sendername);
}


bool UpdateControls(const char** text, float *floats, float *toggles, float *press, int *numControls) {
    int Vcontrols = numControls[0];
    int Tcontrols = numControls[1];
    int Pcontrols = numControls[2];
    int Scontrols = numControls[3];

    int all = Vcontrols + Tcontrols + Pcontrols + Scontrols;
    int v = 0, t = 0, p = 0, s = 0;



    if (spoutcontrols.CheckControls(myControls)) {

        for (int controlID = 0; controlID < all; controlID++) {

            if (myControls[controlID].type == 10) {
                floats[v] = myControls[controlID].value;
                v++;
            }
            if (myControls[controlID].type == 0) {
                toggles[t] = myControls[controlID].value;
                t++;
            }
            if (myControls[controlID].type == 1) {
                press[p] = myControls[controlID].value;
                p++;
            }
            if (myControls[controlID].type == 100) {
                text[s] = myControls[controlID].text.data();
                s++;
            }

        }
        return true;
    }
    return false;
}

void CloseControls() {
    spoutcontrols.CloseControls();
}

这是c#代码:

public unsafe class SystemSpoutSenderNode: IDisposable
    {

        [System.Runtime.InteropServices.DllImport("SpoutControls4vvvv.dll")]
        private static extern void InitializeControls(IntPtr sendername, IntPtr numControls,String[] names, IntPtr types, IntPtr floats, IntPtr toggles, IntPtr press, String[] text);
        [System.Runtime.InteropServices.DllImport("SpoutControls4vvvv.dll")]
        private static extern int CloseControls();
        [System.Runtime.InteropServices.DllImport("SpoutControls4vvvv.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern bool UpdateControls([In, Out] String[] text, [In, Out] float[] floats,  [In, Out] float[] toggles, [In, Out] float[] press, IntPtr numControls);
        [System.Runtime.InteropServices.DllImport("SpoutControls4vvvv.dll")]
        private static extern int ReleaseMemory(IntPtr ptr);


    public void Evaluate(int SpreadMax)
            {           
                        //countControls determines number of controls per type (string,float,toggle,click)                                  
                        int[] controls = countControls(FType);
                        //sumControls will just add up all elements in controls
                        int all = sumControls(controls);

                        //in my code these arrays will get filled with values, deleted here for readability         
                        String[] names = new String[all];   
                        int[] types = new int[all]; 
                        float[] floats = new float[controls[0]];
                        float[] toggles = new float[controls[1]];
                        float[] press = new float[controls[2]];

                        String[] text = new String[controls[3]];

                        //initialze return arrays
                        String[] Rtext = new String[controls[3]];
                        float[] Rfloats = new float[controls[0]];
                        float[] Rtoggles = new float[controls[1]];
                        float[] Rpress = new float[controls[2]];

                        //allocate pointers
                        IntPtr SndrNamePtr = NativeUtf8FromString(FSenderName);
                        IntPtr BinPtr = Marshal.AllocHGlobal(4*sizeof(int));                
                        IntPtr TypePtr = Marshal.AllocHGlobal(all*sizeof(int));
                        IntPtr FloatPtr = Marshal.AllocHGlobal(controls[0]*sizeof(float));
                        IntPtr TogglePtr = Marshal.AllocHGlobal(controls[1]*sizeof(float));
                        IntPtr PressPtr = Marshal.AllocHGlobal(controls[2]*sizeof(float));

                        try
                            {           
                            //copy control info + defaults to pointer   
                            Marshal.Copy(controls, 0, BinPtr, 4);
                            Marshal.Copy(types, 0, TypePtr, all);
                            Marshal.Copy(floats, 0, FloatPtr, controls[0]);
                            Marshal.Copy(toggles, 0, TogglePtr, controls[1]);
                            Marshal.Copy(press, 0, PressPtr, controls[2]);

                            //initialize controls   
                            if (FWrite) InitializeControls(SndrNamePtr,BinPtr,names,TypePtr,FloatPtr,TogglePtr,PressPtr,text);

                            //update controls
                            bool changed = UpdateControls(Rtext,Rfloats,Rtoggles,Rpress,BinPtr);


                            //FF, FT, FS and FP are the outputs in my c# host
                            if (changed){

                                for(int j=0; j<controls[0];j++){
                                FF[j]=Rfloats[j];
                                }           
                                for(int j=0; j<controls[1];j++){
                                FT[j]=FloatToBool(Rtoggles[j]);
                                }
                                for(int j=0; j<controls[3];j++){
                                FS[j]=Rtext[j];
                                }
                            }

                            for(int j=0; j<controls[2];j++){
                                FP[j]=FloatToBool(Rpress[j]);
                                }

                            }

                        finally
                        {
                            Marshal.FreeHGlobal(SndrNamePtr);
                            Marshal.FreeHGlobal(BinPtr);
                            Marshal.FreeHGlobal(FloatPtr);
                            Marshal.FreeHGlobal(TogglePtr);
                            Marshal.FreeHGlobal(PressPtr);  
                        }
                    }
                }   
            }

            public void Dispose()
            {
                CleanUp();
                CloseControls();
            }
}

注意:在进行图形化编程的基于帧的c#主机环境中,c#代码无需预先编译即可运行( vvvv ),因此,我删除了主机的输入(FType,FSenderName)和输出(FF,FS,FP,FT)的特定十进制,以免造成混淆.这些将用于将该代码与其他功能连接"在一起.主机将在每一帧调用评估.

NOTE: the c# code runs without precompiling in a frame-based, c# host environment for graphical programming (vvvv), therefore i've deleted host specific decalarations of inputs (FType,FSenderName) and outputs (FF,FS,FP,FT) to avoid confusion. These will be used to "connect" this code with other functionality. Evaluate will be called every frame by the host.

现在有实际问题:

到目前为止,它在32位上可以正常工作,但是在64位上,我的c#主机崩溃了,没有任何消息.经过一番阅读后,我相信这是由于指针大小在32/64位系统中有所不同,但是我不确定要怎么做/如果这实际上适用于此.如果可以的话,我将非常感谢

it's working fine so far in 32 bit, but in 64 bit my c# host crashes without any message. after some reading i believe this is due to pointer sizes being different in 32/64bit systems, but i'm not exactly sure what to do/if this actually applies here. I would be very thankful if you could

  • 向我解释如何(以及为什么)使此代码在64位上运行
  • 指出您可能会发现的其他错误-我是c ++的新手,还是c#的初学者,所以我非常有信心在这里有很多改进.特别是:内存泄漏并将值从c ++传递到c#,反之亦然... uiuiui.

我知道我不应该将指针转换为64位的int,所以我尝试的最后一件事是将其更改为

I've understood that I shouldn't cast a pointer to an int in 64 bit, so the last thing I've tried is to change from

int Vcontrols = numControls[0];
int Tcontrols = numControls[1];
int Pcontrols = numControls[2];
int Scontrols = numControls[3];

int Vcontrols = (INT_PTR)numControls[0];
int Tcontrols = (INT_PTR)numControls[1];
int Pcontrols = (INT_PTR)numControls[2];
int Scontrols = (INT_PTR)numControls[3];

但是没有运气,因此即使这是正确的改进,我也要发布我原来的问题.

but with no luck, therefore I'm posting my original problem, even if this is a correct improvement(?).

感谢@dkackman指出了一个不清楚的地方:我的cpp代码使用本机32位dll调用作为源代码(SpoutControls.h)附带的函数.它不是32位dll本身的来源,但声明了(据我所知)用于访问与32位dll相同的共享内存的函数. 如果这可能是问题,我也可以在此处复制粘贴代码? 也可以在此处

thanks to @dkackman for pointing out one unclear point: my cpp code calls functions which come as source code (SpoutControls.h) with the native 32 bit dll. It's not the source for the 32 bit dll itself but declares the functions used to (as far as i can tell) access the same shared memory as the 32 bit dll. I can also copy paste the code here if this might be the problem? Also can be found here

谢谢.

推荐答案

恐怕您不走运.如果您的进程是64位的,则无论您尝试多少,都将无法加载该32位的dll.

I am afraid you are out of luck. If your process is 64bit, you won't be able to load that 32bit dll, no matter how much you try.

可以我在Windows上将32位DLL加载到64位进程中吗?

来自 https://msdn.microsoft.com/zh-CN/library/windows/desktop/aa384231(v=vs.85).aspx

在64位Windows上,64位进程无法加载32位动态链接 库(DLL).

On 64-bit Windows, a 64-bit process cannot load a 32-bit dynamic-link library (DLL).

在无法访问其源代码的情况下,唯一的选择是将主机转换为32bit,否则将弄清楚如何在32bit进程中托管32bit插件,并使用某种IPC从64bit主机进程与其进行通信.

Without access to its source, your only option would be to convert your host to 32bit or otherwise figure out how to host the 32bit plugin in a 32bit process and use some sort of IPC to communicate with it from a 64bit host process.

所以我的猜测是,这与您的包装器,数组传递或互操作代码无关.

So my guess is that this has nothing to do with your wrapper, array passing or interop code.

这篇关于我的c ++和c#互操作崩溃为64位,为什么?指针大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆