Доступ к публичной памяти классов из C ++ с использованием C - PullRequest
1 голос
/ 20 марта 2009

Приветствую Всех.

В настоящее время я пишу многоязычную программу на C, C ++ и fortran в UNIX, к сожалению, я сталкиваюсь с «Ошибка сегментации», когда пытаюсь выполнить после компиляции.

Я сузил проблему до интерфейса между разделами C ++ и C моей программы. Первый раздел состоит из main.ccp и SA.cpp, а второй CFE.c.

В SA.cpp существует класс SimAnneal с открытыми векторами DensityArray и ElementArray. Порядок выполнения программы следующий:

  1. Создание объекта SimAnneal 'Obj1' и вызов функции ObjFunction ()

  2. Эта функция инициализирует размеры векторов

  3. Вызовите CFE (...) с указателями на оба вектора и их длину.

  4. CFE.c редактирует элементы данных векторов напрямую с помощью указателей

  5. ObjFunction () использует данные EnergyArray (и, возможно, DensityArray).

Соответствующий скрипт приведен ниже для всех источников:

main.cpp

#include "SA.h" 

int main() 
{   
    SimAnneal Obj1;

    Obj1.ObjFunction();

    return 0;
}

SA.h

class SimAnneal 
{
    void Initialize ();
    ...
  public
    std::vector<float> DensityArray; 
    std::vector<float> EnergyArray;
    double ObjFunction ();
    ...
}

SA.cpp

#include "CFE.h"

void SimAnneal::Initialize ()
{
    int length = 15;
    EnergyArray.resize(length);
DensityArray.resize(length);
}

double SimAnneal::ObjFunction () 
{
    Initialize ();

    CFE(&DensityArray[0], &EnergyArray[0], DensityArray.size()); 

      // sends pointers of both arrays to CFE.c, which will then 
      // directly modify the array

    double SumStrainEnergy = 0;

    for (int i = 0; i < EnergyArray.size(); i++)
    {
        SumStrainEnergy += EnergyArray[i];  //Effectively sum of array 
                                            //engy[] from CFE.c
    }

    return SumStrainEnergy;
}

CFE.h

#ifdef __cplusplus
extern "C" {
#endif 

void CFE(float density[], float energy[], int NumElem);

#ifdef __cplusplus
 }
#endif

CFE.c

void CFE(float density[], float energy[], int NumElem)
{
    ...

    float * dens;
    dens = density;  //pass pointer of array density[0] in SA.cpp to CFE.c

    for(n=0; n<NumElem; n++)
    { ... modify dens (e.g. DensityArray from SA.cpp) ... }

    float * engy;
    engy = energy; //pass pointer of array energy[0] in SA.cpp to CFE.c

    for(n=0; n<NumElem; n++)
    { ... modify engy (e.g. EnergyArray from SA.cpp) ... }   
}

Я вызываю незаконный доступ к памяти, пытаясь получить доступ к векторным элементам из части C моей программы? Есть ли верный способ разрешить это?

Любая помощь будет очень ценной.

Ответы [ 5 ]

11 голосов
/ 20 марта 2009

Если бы вы оставались в пределах вектора, то, что вы делаете, казалось бы, нормально.

Вы можете обрабатывать std :: vector точно так же, как если бы это был массив C, выполняя то, что вы делаете - беря адрес первого элемента. Стандарт C ++ был изменен, чтобы разрешить использование такого рода.

В настоящее время не удается найти копию C ++ Технического исправления 2003, но, по-видимому, соответствующий раздел ref - 23.2.4,

1 голос
/ 20 марта 2009

Код, который вы опубликовали, выглядит нормально - вам нужно будет предоставить более подробную информацию, если вы хотите, чтобы проблема была отлажена. На самом деле, если вы запустите программу в отладчике, она сможет точно сказать вам, какая строка кода вызывает исключение (вам, возможно, придется искать в стеке вызовов), или просто пройтись по программе, пока она не вылетит.

Что касается путаницы относительно того, может ли вектор рассматриваться как массив C, то он определенно может получить адрес первого элемента (т.е. &vect[0]) - если вектор содержит элементы.

Стандарт C ++ 03 говорит об этом vector<> в 23.2.4:

Элементы вектора хранятся смежно, что означает, что если v - это vector<T, Allocator>, где T - это какой-то тип, отличный от bool, то он подчиняется тождеству &v[n] == &v[0] + n для всех 0 <= n < v.size()

Обратите внимание, что это не было явно указано в стандарте C ++ 98 (но все еще было намерением).

См. Также статью Херба Саттера:

Обратите внимание, что vector<bool> нельзя рассматривать как массив C - это особый случай, поскольку элементы в vector<bool> не сохраняются как bool.

0 голосов
/ 20 марта 2009

Что такое содержание ДОВСЕ ()?

Почему бы не определить CFE () как; void CFE (float * плотность, float * energy, int NumElem);

Так что вам не нужно дурачиться с кастами и просто делать; плотность [я] = ... внутри ваших петель?

0 голосов
/ 20 марта 2009

Код, который вы опубликовали, верен. При условии, что каждый доступ к элементу массива внутри CFE() находится в пределах, вы не должны получать ошибку сегментации. Попробуйте запустить вашу программу под valgrind и посмотрите, сообщает ли она что-нибудь необычное.

0 голосов
/ 20 марта 2009

Вы не можете этого сделать. Класс Vector не совпадает с массивом, подобным C.

Вы должны преобразовать его в обычный массив C, прежде чем передавать его в функцию CFE.

Edit: Видимо мой ответ неверный. Проверьте сообщение Нейла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...