Poniższy przykład demonstruje wywołanie z poziomu C Fortranowskiej funkcji liczącej silnię: fact:
/* C source file - calls FORTRAN function
compile in medium or large memory model */
int __fortran fact(int N);
/* Fortran keyword caises C to use FORTRAN calling and naming convenction.
Integer parameter passed by value */
main()
{
int x=3,y=4;
printf("The factorial of x is %4d",fact(x));
printf("The factorial of y is %4d",fact(y));
printf("The factorial of x+y is %4d",fact(x+y));
}
C FORTRAN source file - factorial function
C
C N is received by value, becausse of VALUE attribute
C NOTRUNCATE - no truncate identifier name to 6 characters
$NOTRUNCATE
INTEGER *2 FUNCTION FACT (N)
INTEGER*2 N[VALUE]
C
INTEGER *2 I
FACT = 1
DO 100 I=1,N
FACT=FACT*I
100 CONTINUE
RETURN
END
Ponieważ w przeciwieństwie do poprzedniego przykładu parametry nie ulegały zmianie zdecydowano przesłać je przez wartość (sposób default dla języka C). Wymagało to określenia atrybutu VALUE dla przesyłanych parametrów w definicji funkcji Fortranowskiej.
Wywoływanie podprogramów Pascalowskich z poziomu C
W pascalu mamy do czynienia z dwoma rodzajami podprogramów: procedurą i funkcją.Procedura nie zwraca wartości, funkcja zwraca.
Procedura Pascalowa wywoływana z poziomu C
Procedura Pascalowska maxparam jest odpowiednikiem takiej samej w języku Fortran:
/* C source file - calls Pascal procedure. Compile in medium or large memory model */
void __pascal maxparam(int __near *a, int __near*b);
/* Declare as void becouse there is no return value.The __pascval keyword causes C to use PASCAL calling and naming convenction. Two integer parameters passed by near adress */
main()
{
int a=5,b=7;
printf("a=%d, b=%d",a,b);
maxparam(&a,&b);
printf("a=%d,b=%d",a,b);
}
{Pascal source code = maxparam procedure }
MODULE Psub;
PROCEDURE Maxparam(var a:integer;var:b:integer);
begin
if a>b then
b:=a
else
a:=b;
end;
end.
W powyższym przykładzie ponieważ parametry przesyłane były przez adress near można było użyć w procedurze słowa VAR. Dla adresu far konieczne byłoby użycie VARS. Konwencja pascalowa określana jest przez słowo kluczowe __pascal
Wywołanie funkcji Pascalowskiej z poziomu C
Funkcja jest odpowiednikiem funkcji z Fortranu:
/* C source file - calls PASCAL function
compile in medium or large memory model */
int __pascal fact(int N);
/* Pascal keyword caises C to use PASCAL calling and naming convenction.
Integer parameter passed by value */
main()
{
int x=3,y=4;
printf("The factorial of x is %4d",fact(x));
printf("The factorial of y is %4d",fact(y));
printf("The factorial of x+y is %4d",fact(x+y));
}
{ Pascal source code - factorial function }
MODULE Pfun;
FUNCTION Fact (n:integer):integer;
begin
fact:=1;
while n>0 do
begin
fact :=fact*n;
n:=n-1;
end;
end;
end.
Dla języka C++ interfejs pomiędzy językiem C++ i innym językiem wyższego poziomu odbywa się poprzez odniesienie do C: extern "C"
{
void prin; // odwołanie do funkcji w języku C
}
extern "C" { int __pascal fact(int n); } //deklaruje funkcję napisaną w konwencji Pascala
Owołanie C do języków asemblerowych
Najczęstszym sposobem pisania "wstawek" asemblerowych jest użycie tzw. inline asemblera. Można również tworzyć samodzielne moduły w dostępnych asemblerach. Jednak asembler "inline" jest bardziej efektywny od samodzielnych asembleró. Oto kilka zalet takiego podejścia:
1. kod asemblera inline włączony jest do kodu języka C. Kod napisany w asemblerach zewnętrznych musi być umieszczony w oddzielnych plikach.
2. krótkie wstawki asemblerowe mogą optymalizować program
3. nie wymagają też wykonywania wywołania funkcji tak jak by to było a asemblerach zewnętrznych . Są to po prostu linie kodu tyle tylko, że w asemblerze
Nie będziemy mówili o asemblerach zewnętrznych. Powiemy tylko parę słów o asemblerze "inline";
Zakres użycia tej techniki jest bardzo szeroki jednak najczęściej stosowany jest do:
- poprawiania szybkości programu
-zmniejsza potrzeby co do zajętości pamięci
-użycie funkcji DOS i BIOS z instrukcja INT
Umożliwia umieszczenie kodu asemblerowego bezpośrednio w kodzie C. Jest wbudowany w kompilator i nie wymaga zewnętrznych asemblerów kod asemblerowy poprzedzony musi zostać słowem kluczowym asm:
__asm
{
mov ah,2
mov dl,7
int 21h
}
kod ten równoważny jest zapisowi:
__asm mov ah,2
__asm mov dl,7
__asm int 21h
Jeśli słowo kluczowe asm używane jest przed każdą instrukcja wtedy mogą być one umieszczone w jednej lini:
__asm mov ah,2 __asm mov dl,7 __asm int 21h
Poniższy przykład ilustruje użycie funkcji napisanej w asemblerze inline wywołanej w kodzie języka C:
#include
int power2(int num,int power);
void main(void)
{
printf("3 times 2 to the powerr of 5 is %d
",power2(3,5));
}
int power2(int num,int power)
{
__asm
{
mov ax,num;
mov cx,power;
shl ax,cl;
}
/* return with result in ax */
}
W bloku __asm możemy wywoływać funkcje biblioteczne języka C: wykonuje to instrukcja CALL:
#include
char format[]="%s %s";
char hello[] = "Hello";
char world[] = "world";
void main(void)
{
__asm
{
mov ax, offset world
push ax
mov ax, offset hello
push ax
mov ax, offset
push ax
call printf
}
}
funkcja printf zbiera swoje argumenty, które umieszczane są na stosie
powyższy kod emuluje zapis C:
printf(format,hello,world);