그냥... 생각나서 적어봅니다만... C 에서...함수호출에관해..

익명 사용자의 이미지

그냥... 생각나서 적어봅니다만... C 에서...함수호출에관해..

가끔 라이브러리간 함수명(동일명) 충돌이 일어날때가 있는데요...

왜 이런기능을 제공하지 않을까요...

예를들면...

aaa.a 라이브러리에.. abc() 함수가있고..
bbb.a 에도 abc() 있고...

프로그래밍할때.. 두라이브러리를 포함시키고...
aaa:abc() 등으로 구별해서 호출할수 있도록하면 좋을텐데요..
그냥 abc() 로하면..디폴트 우선순위(먼저나오는등)의 순위를 적용해서 링크해주면 얼마나 좋을까요...

왜 이기능이 없는지 좀 이해가 안되는데.. 저만그런가요..

익명 사용자의 이미지

cpp엔 이미 있는 기능입니다
괜히 c+1 인 언어는 아니죠^^

익명 사용자의 이미지

C++이라해도.. C 오브젝트만 제공했는데 그게되나요?

된다면 정확히 어떤표현으로 되나요?

익명 사용자의 이미지

윗분이 C++ 에 있다고 말씀하신건 함수의 오버로딩을 말씀하신것같구요
그런데 이때는 함수이름이 같아도 지원이되지만, 단 이때 매개변수형태는 달라야합니다.
그리고 이때 파일이 다르고 같고는 고려하지않아도됩니다. 여기서의 문제는 파일이 같고 다르냐가 아니라 같은함수이름의 중복되는 함수를 지원하느냐 안하느냐의 차이점이기때문에요. C++ 에서 같은 함수이름은 중복되어도 지원이되지만 , 매개변수 형식은 달라야합니다.
따라서 님께서 말씀하시는 a.c 와 b.c 에 같은 함수이름도 같고 매개변수 형식도 같은 함수가있으면 컴파일오류납니다.

그리고 이건 다시한번 말씀드리지만 같은파일,다른파일의 문제가아니라 함수 오버로딩이지원되는지 여부와 , 매개변수형식은 다르다는데 있구요.

파일이 다른건 실행파일의 생성에 전혀 고려대상이 되지않습니다.그냥 편의상 그렇게 개발하는것 뿐이지요..^^

익명 사용자의 이미지

윗 분은 C++의 namespace 말씀하시는 듯...

madhatter의 이미지

namespace 인듯..

원글 쓴 분의 경우 C++의 namespace 처럼 하려면 접두어로 구분되는 wrapper 함수를 각각 만들고 그 안에서 local 함수처럼 사용하면 됩니다.

태훈의 이미지

이런건 어떨까요?

#include <stdio.h>
#include <stdarg.h>
 
struct libio {
  int (*print)(const char *str, ...);
};
 
static int
my_print(const char *fmt, ...)
{
  va_list args;
  int ret;
  va_start(args, fmt);
  ret = printf(fmt, args);
  va_end(args);
  return ret;
}
 
struct libio lib1 = {
  .print = my_print,
};
 
struct libio lib2 = {
  .print = my_print,
};
 
int main(void)
{
  lib1.print("lib1\n");
  lib2.print("lib2\n");
  return 0;
}

Just do it!

익명 사용자의 이미지

이미 링커가 그거 다 하고 있는데요.
gnu ld에 더 설정하는게 있는지는 모르지만 보통 설치만하고 손 안댄 상태에서는 순서대로 뒤지다가 먼저 나오는 순서대로 링크해줘요.
비주얼스튜디오는 2003 이후로 어떻게 바뀌었는지 모르는데 그전에는 역시 순서대로 나오는대로 링크했죠.
어떤 링커를 쓰길래 그러시는지?

익명 사용자의 이미지

위에분들 답변감사합니다...

일단 namespace 가 상당부분 비슷한면이 없지 않지만...이건 소스가 있어미리부터 정의해야가능하죠...

요지는 라이브러리간 함수명의 충돌인데요... 이미 두라이브러리로 제공되었고..(소스가없음)

이때는 해결이 안되지 않나요?

-----------------------------------------------
그리고.. GNU LD 로하면된다 하신분..

처음글에도 예를들어 적었듯이... aaa.a, bbb.a 에 abc() 라는동일명의 두함수가 있을때..

어떻게 구별호출할수 있을지.. 간단한 예제좀 알려주시면 감사하겠습니다.

gilgil의 이미지

function을 static으로 선언을 하면 그 모듈(*.c)내에서만 사용이 가능하도록 됩니다.

익명 사용자의 이미지

이미 라이브러리로 제공되었고.. 일단 소스를 수정할수 없다는 가정입니다..

또한.. static 로 사용할성격의 함수들이 아니라는가정이죠...

많은경우.. 각기 다른회사에서 제공된 다른기능의 lib중... 우연히.. 중복되는 함수명이 존재할수 있습니다..

이때.. 특정(lib제공)회사에.. (그회사입장에선 멀쩡한소스를)소스자체를 변경해달라는 요청을하기 곤란하죠..

ymir의 이미지

서로 다른 library 에 동일한 extern 함수가 있는 경우, link order 에 의해 먼저 걸리는 녀석이 실행됩니다.

하나의 함수만 실행되지만 운이 좋다면 link order 를 조절해서 필요한 녀석만 쓸 수 있을겁니다.

모두 써야 하는 경우라면 dlopen 패밀리로 wrapping 하는 모듈을 만들어 주면 될 것 같네요.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

ymir의 이미지

libfoo.c

#include <stdio.h>
 
void hello(void)
{
	printf("hello foo~!\n");
}

libbar.c

#include <stdio.h>
 
void hello(void)
{
	printf("hello bar~!\n");
}

foobar.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
 
struct libs
{
	const char *path;
	void *handle;
	char *error;
 
	void (*hello)(void);
};
 
extern void hello(void);
 
static int dl_init(struct libs *lib)
{
	void *handle;
 
	handle = dlopen(lib->path, RTLD_LAZY);
	if (handle == NULL)
	{
		lib->error = dlerror();
		return -1;
	}
 
	dlerror();    /* Clear any existing error */
 
	*(void **) (&lib->hello) = dlsym(handle, "hello");
	if ((lib->error = dlerror()) != NULL)
		return -1;
 
	lib->handle = handle;
 
	return 0;
}
 
static void dl_fini(struct libs *lib)
{
	if (lib->handle)
	{
		dlclose(lib->handle);
		lib->handle = NULL;
	}
}
 
int main(void)
{
	struct libs foo, bar;
 
	memset(&foo, 0x00, sizeof(struct libs));
	memset(&bar, 0x00, sizeof(struct libs));
 
	foo.path = "./libfoo.so";
	if (dl_init(&foo) < 0)
	{
		fprintf(stderr, "dl_init for libfoo is failed : %s\n", foo.error);
		return (EXIT_FAILURE);
	}
 
	bar.path = "./libbar.so";
	if (dl_init(&bar) < 0)
	{
		fprintf(stderr, "dl_init for libbar is failed : %s\n", bar.error);
		return (EXIT_FAILURE);
	}
 
	printf("by calling foo : "); fflush(stdout);
	foo.hello();
	printf("by calling bar : "); fflush(stdout);
	bar.hello();
 
	dl_fini(&foo);
	dl_fini(&bar);
 
	printf("by link order : "); fflush(stdout);
	hello();
 
	return (EXIT_SUCCESS);
}

$ gcc -g -W -Wall -fPIC -shared -o libfoo.so libfoo.c 
$ gcc -g -W -Wall -fPIC -shared -o libbar.so libbar.c 
 
$ gcc -g -W -Wall -L . -o foobar foobar.c -l foo -l bar -ldl
$ ldd foobar
	linux-gate.so.1 =>  (0x00df3000)
	libfoo.so => not found
	libbar.so => not found
	libdl.so.2 => /lib/libdl.so.2 (0x007b6000)
	libc.so.6 => /lib/libc.so.6 (0x005e0000)
	/lib/ld-linux.so.2 (0x005be000)
$ LD_LIBRARY_PATH=. ./foobar
by calling foo : hello foo~!
by calling bar : hello bar~!
by link order : hello foo~!
 
$ gcc -g -W -Wall -L . -o foobar foobar.c -l bar -l foo -ldl
$ ldd foobar
	linux-gate.so.1 =>  (0x00a9a000)
	libbar.so => not found
	libfoo.so => not found
	libdl.so.2 => /lib/libdl.so.2 (0x007b6000)
	libc.so.6 => /lib/libc.so.6 (0x005e0000)
	/lib/ld-linux.so.2 (0x005be000)
$ LD_LIBRARY_PATH=. ./foobar
by calling foo : hello foo~!
by calling bar : hello bar~!
by link order : hello bar~!
$ 

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

익명 사용자의 이미지

잘보았습니다. 되긴 하지만....
동적라이브러리로 만들어야하고.. 일일이 함수마다 레핑해줘야하는 귀찮음이 상당하네요...
또한 함수콜에 있어 상당한 성능저하가 있지 않을까 예상됩니다.

아무튼 상세한설명 감사드립니다.

익명 사용자의 이미지

아.. 성능저하는 초기 한번일듯하니.. 제외하겠습니다.^^