2015-03-24 3 views
1

В качестве дополнения к этому post, я получил типы, которые имеют как сами производные типы. Пример ниже:Фортран производные типы, содержащие производные типы, которые должны быть доступны из C

module simple 
use iso_c_binding 

TYPE SIMPLEF 
    INTEGER :: A 
    INTEGER, POINTER :: B, C(:) 
END TYPE SIMPLEF 

TYPE COMPLEXF 
    INTEGER :: X 
    TYPE (SIMPLEF) :: Y 
END TYPE COMPLEXF 
end module simple 

Цель состоит в том, как в приведенном выше пост, имеют аналогичные производные типы в С и, чтобы иметь возможность передавать значения и обратно Fortran. Решение можно увидеть here. Однако здесь это не только производный тип, но и производный тип с элементом, который является производным типом. Мне нужно создать для COMPLEXF подпрограммы для каждого члена Y, то есть SETY_A, QUERYY_A, SETY_B, QUERYY_BSIZE, SQUERYY_B и т. Д.? Или есть лучший способ приблизиться к этому?

ответ

2

Такой же подход можно использовать. Что лучше всего зависит от того, что, по вашему мнению, является лучшим способом для ваших клиентов C взаимодействовать с вашими объектами Fortran. Некоторые мысли должны быть помещены в это, прежде чем писать слишком много кода.

Как показано, существование y компонента является деталью, что код C, вероятно, не нужно заботиться о - вместо вызова процедуры sety_a вы могли бы просто назвать его set_a.

Если в компоненте типа COMPLEXF будет много операций, и вы хотите избежать уровня косвенности или если таких компонентов COMPLEXF, то вы можете использовать адрес C подобъекта, который соответствует этому компоненту как непрозрачный дескриптор.

Ради примера, изменить GetHandle и ReleaseHandle процедур в linked answer для работы с COMPLEXF типа, как тип верхнего уровня (то есть - заменить COMPLEXF для всех выступлений SIMPLEF в этом ответе). Затем можно написать QueryYHandle процедуру или аналогичный, вдоль линий:

FUNCTION QueryYHandle(handle) RESULT(y_handle) 
    TYPE(C_PTR), INTENT(IN), VALUE :: handle 
    TYPE(C_PTR) :: y_handle 
    TYPE(COMPLEXF), POINTER :: p 
    !*** 
    CALL C_F_POINTER(handle, p) 
    y_handle = C_LOC(p%y) 
END FUNCTION QueryYHandle 

Теперь вы можете работать с ручкой на SIMPLEF подобъекте непосредственно - с помощью точно такой же запрос */Set * процедуры, как в связанном ответ ,

Там нет необходимости писать процедуры для освобождения объекта, выдвинутого y_handle в этом случае, поскольку срок службы субобъекта, связанный с y компонентом определяется время жизни объекта, который имеет тот субобъект - это субобъект воля уходят, когда вызывается ReleaseHandle для супер-объекта COMPLEXF.

Обратите внимание на то, что в подходе, как указано выше, не существует защиты для неправильного обращения дескриптора между языками (например, если код C случайно вызвал процедуру, предназначенную для работы с дескриптором COMPLEXF с который фактически был для объекта SIMPLEF). Если это проблематично, тогда защита может быть добавлена, возможно, путем связывания типа дескриптора с адресом C в объекте, используемом как непрозрачный дескриптор, и проверки этого типа дескриптора, прежде чем пытаться связать указатель Fortran с объектом, назначенным адресом C.

+0

Спасибо за подробный ответ. Поэтому в Fortran я все еще могу изменить компонент y SIMPLEF переменной COMPLEXF, а затем C вернет обновленный компонент с помощью компоновки C_LOC. Я предполагаю, что если бы я хотел, я мог бы еще получить доступ к подкомпонентам y на стороне C на этом этапе, или я мог бы просто приравнять y (уже полученный с C_LOC) к другой переменной типа SIMPLEF с обновленными значениями в C. – Stam