复制结构时System.AccessViolationException异常 我在C++ /CLI项目中有这个C++函数(非托管代码)。

复制结构时System.AccessViolationException异常 我在C++ /CLI项目中有这个C++函数(非托管代码)。,c++,struct,c++-cli,C++,Struct,C++ Cli,BMP Image; Image.ReadFromFile(filePath); HsvColor hsvPixel; RGBApixel startPixel; for (int i = 0; i < Image.TellWidth(); i++) { for (int j = 0; j < Image.TellHeight(); j++) { startPixel = *(Image(i, j));

    BMP Image;
    Image.ReadFromFile(filePath);
    HsvColor hsvPixel;
    RGBApixel startPixel;
    for (int i = 0; i < Image.TellWidth(); i++) {
        for (int j = 0; j < Image.TellHeight(); j++) {


            startPixel = *(Image(i, j));
            hsvPixel = RgbToHsv(startPixel);


            RGBApixel finalPixel = HsvToRgb(hsvPixel);
            *(Image(i, j)) = finalPixel;

        }
    }
ebmpBYTE是类型定义的无符号字符

两种方法的代码:

RGBApixel HsvToRgb(HsvColor hsv)
{
    RGBApixel rgb;
    unsigned char region, remainder, p, q, t;

    if (hsv.Saturation == 0)
    {
        rgb.Red = hsv.Value;
        rgb.Green = hsv.Value;
        rgb.Blue = hsv.Value;
        rgb.Alpha = 1;
        return rgb;
    }

    region = hsv.Hue / 43;
    remainder = (hsv.Hue - (region * 43)) * 6;

    p = (hsv.Value * (255 - hsv.Saturation)) >> 8;
    q = (hsv.Value * (255 - ((hsv.Saturation * remainder) >> 8))) >> 8;
    t = (hsv.Value * (255 - ((hsv.Saturation * (255 - remainder)) >> 8))) >> 8;

    switch (region)
    {
    case 0:
        rgb.Red = hsv.Value; rgb.Green = t; rgb.Blue = p;
        break;
    case 1:
        rgb.Red = q; rgb.Green = hsv.Value; rgb.Blue = p;
        break;
    case 2:
        rgb.Red = p; rgb.Green = hsv.Value; rgb.Blue = t;
        break;
    case 3:
        rgb.Red = p; rgb.Green = q; rgb.Blue = hsv.Value;
        break;
    case 4:
        rgb.Red = t; rgb.Green = p; rgb.Blue = hsv.Value;
        break;
    default:
        rgb.Red = hsv.Value; rgb.Green = p; rgb.Blue = q;
        break;
    }

    return rgb;
}

HsvColor RgbToHsv(RGBApixel rgb)
{
    HsvColor hsv;
    unsigned char rgbMin, rgbMax;

    rgbMin = rgb.Red < rgb.Green ? (rgb.Red < rgb.Blue ? rgb.Red : rgb.Blue) : (rgb.Green < rgb.Blue ? rgb.Green : rgb.Blue);
    rgbMax = rgb.Red > rgb.Green ? (rgb.Red > rgb.Blue ? rgb.Red : rgb.Blue) : (rgb.Green > rgb.Blue ? rgb.Green : rgb.Blue);

    hsv.Value = rgbMax;
    if (hsv.Value == 0)
    {
        hsv.Hue = 0;
        hsv.Saturation = 0;
        return hsv;
    }

    hsv.Saturation = 255 * long(rgbMax - rgbMin) / hsv.Value;
    if (hsv.Saturation == 0)
    {
        hsv.Hue = 0;
        return hsv;
    }

    if (rgbMax == rgb.Red)
        hsv.Hue = 0 + 43 * (rgb.Green - rgb.Blue) / (rgbMax - rgbMin);
    else if (rgbMax == rgb.Green)
        hsv.Hue = 85 + 43 * (rgb.Blue - rgb.Red) / (rgbMax - rgbMin);
    else
        hsv.Hue = 171 + 43 * (rgb.Red - rgb.Green) / (rgbMax - rgbMin);

    return hsv;
}
编辑:我使用调试器查看RgbToHsv函数是如何执行的。循环第一次运行时,startPixel始终是相同的(应该是这样的)。但是当我在VisualStudio中单击“单步执行”并查看代码如何在函数中执行时,参数(“rgb”)总是与startPixel完全不同!我是调试新手,因此可能会错误地解释问题。但现在我更困惑了


我还应该提到代码运行时的结果。它输出图像,但输出图像只是一种随机的单色(例如完全蓝色),而它应该与输入图像相同。

确切的问题是@HansPassant在其评论中描述的问题:

您可能正在与呼叫约定不匹配作斗争。C++/CLI编译器编译的代码的默认值是_clrcall,即使用_cdecl构建的C函数上的redrum。您必须让编译器知道其他代码不是以相同的方式构建的。我们看不到你所使用的包含你的语法,考虑在他们之前把“PrimaPrimar”管理(推、关),然后在它们后面加上PrimaMac(POP)。
我解决这个问题的方法是删除所有的#pragma unmanaged/#pragma managed行,而是将所有应该用本机代码编译的cpp文件设置为不支持他所描述的clr。

您需要向我们展示更多的代码。至少,
HsvColor
RGBApixel
的定义。我们还需要知道Image(i,j)在做什么:如果这些括号是正确的,那么它显然不是一个愚蠢的结构。我们不关心将HSV转换为RGB的数学问题,但我们可能需要知道该方法是如何声明的。@DavidYaw我添加了您要求的内容。@Pux您应该为
HsvToRgb
RgbToHsv
函数添加代码。还需要
operator()(inti,intj)
的实现细节。@MKR好的,我也添加了这个。感谢您的帮助。@Pus像素的声明是什么?
RGBApixel HsvToRgb(HsvColor hsv)
{
    RGBApixel rgb;
    unsigned char region, remainder, p, q, t;

    if (hsv.Saturation == 0)
    {
        rgb.Red = hsv.Value;
        rgb.Green = hsv.Value;
        rgb.Blue = hsv.Value;
        rgb.Alpha = 1;
        return rgb;
    }

    region = hsv.Hue / 43;
    remainder = (hsv.Hue - (region * 43)) * 6;

    p = (hsv.Value * (255 - hsv.Saturation)) >> 8;
    q = (hsv.Value * (255 - ((hsv.Saturation * remainder) >> 8))) >> 8;
    t = (hsv.Value * (255 - ((hsv.Saturation * (255 - remainder)) >> 8))) >> 8;

    switch (region)
    {
    case 0:
        rgb.Red = hsv.Value; rgb.Green = t; rgb.Blue = p;
        break;
    case 1:
        rgb.Red = q; rgb.Green = hsv.Value; rgb.Blue = p;
        break;
    case 2:
        rgb.Red = p; rgb.Green = hsv.Value; rgb.Blue = t;
        break;
    case 3:
        rgb.Red = p; rgb.Green = q; rgb.Blue = hsv.Value;
        break;
    case 4:
        rgb.Red = t; rgb.Green = p; rgb.Blue = hsv.Value;
        break;
    default:
        rgb.Red = hsv.Value; rgb.Green = p; rgb.Blue = q;
        break;
    }

    return rgb;
}

HsvColor RgbToHsv(RGBApixel rgb)
{
    HsvColor hsv;
    unsigned char rgbMin, rgbMax;

    rgbMin = rgb.Red < rgb.Green ? (rgb.Red < rgb.Blue ? rgb.Red : rgb.Blue) : (rgb.Green < rgb.Blue ? rgb.Green : rgb.Blue);
    rgbMax = rgb.Red > rgb.Green ? (rgb.Red > rgb.Blue ? rgb.Red : rgb.Blue) : (rgb.Green > rgb.Blue ? rgb.Green : rgb.Blue);

    hsv.Value = rgbMax;
    if (hsv.Value == 0)
    {
        hsv.Hue = 0;
        hsv.Saturation = 0;
        return hsv;
    }

    hsv.Saturation = 255 * long(rgbMax - rgbMin) / hsv.Value;
    if (hsv.Saturation == 0)
    {
        hsv.Hue = 0;
        return hsv;
    }

    if (rgbMax == rgb.Red)
        hsv.Hue = 0 + 43 * (rgb.Green - rgb.Blue) / (rgbMax - rgbMin);
    else if (rgbMax == rgb.Green)
        hsv.Hue = 85 + 43 * (rgb.Blue - rgb.Red) / (rgbMax - rgbMin);
    else
        hsv.Hue = 171 + 43 * (rgb.Red - rgb.Green) / (rgbMax - rgbMin);

    return hsv;
}
RGBApixel* BMP::operator()(int i, int j)
{
 using namespace std;
 bool Warn = false;
 if( i >= Width )
 { i = Width-1; Warn = true; }
 if( i < 0 )
 { i = 0; Warn = true; }
 if( j >= Height )
 { j = Height-1; Warn = true; }
 if( j < 0 )
 { j = 0; Warn = true; }
 if( Warn && EasyBMPwarnings )
 {
  cout << "EasyBMP Warning: Attempted to access non-existent pixel;" << endl
       << "                 Truncating request to fit in the range [0,"
       << Width-1 << "] x [0," << Height-1 << "]." << endl;
 }  
 return &(Pixels[i][j]);
}
RGBApixel** Pixels;