Почему бы не добавить промежуточное ПО с чем-то вроде этого:
class RequestMiddleware(object):
thread_local = threading.local()
def process_request(self, request):
RequestMiddleware.thread_local.current_user = request.user
и позже в вашем коде (особенно в сигнале в этом разделе):
thread_local = RequestMiddleware.thread_local
if hasattr(thread_local, 'current_user'):
user = thread_local.current_user
else:
user = None
Я работал над продуктом электронной коммерции несколько лет назад, и мы сделали это путь вы описали. Но мы добавили еще один слой для обработки нескольких атрибутов на одном продукте (размер и цвет, как вы сказали). Мы отслеживали каждый атрибут отдельно, и у нас была таблица «SKU», в которой перечислялась каждая комбинация атрибутов, разрешенная для каждого продукта. Что-то вроде этого:
attr_id attr_name
1 Size
2 Color
sku_id prod_id attr_id attr_val
1 1 1 Small
1 1 2 Blue
2 1 1 Small
2 1 2 Red
3 1 1 Large
3 1 2 Red
Позже мы добавили отслеживание запасов и другие функции, и мы связали их с идентификаторами sku ID, чтобы мы могли отслеживать каждый по отдельности.
-121--3383584- В этом примере не используются никакие условия и исключения.
(Есть некое скрытое состояние при коротком замыкании ИЛИ).
Использование рекурсии позволяет избежать петель.
public class OneToHundered {
public static boolean exit() {
System.exit(0);
return true;
}
public static boolean printToHundered(int i) {
boolean r;
System.out.println(i);
r = (i<100) || exit();
printToHundered(i+1);
return r;
}
public static void main(String[] args) {
printToHundered(1);
}
}
-121--1851134- Это не слишком сложно сделать вручную, но будет зависеть от размера интерфейса. Случаи, когда я делал это, чтобы разрешить использование нашей библиотеки C++ из чистого кода C, и, таким образом, SWIG не был большой помощью. (Может быть, SWIG можно использовать для этого, но я не гуру SWIG и это казалось нетривиальным)
Все, что мы в итоге сделали:
Итак, такой класс, как этот (заголовок C++)
class MyClass
{
public:
explicit MyClass( std::string & s );
~MyClass();
int doSomething( int j );
}
Будет сопоставляться с C-интерфейсом, таким как этот (заголовок C):
struct HMyClass; // An opaque type that we'll use as a handle
typedef struct HMyClass HMyClass;
HMyClass * myStruct_create( const char * s );
void myStruct_destroy( HMyClass * v );
int myStruct_doSomething( HMyClass * v, int i );
Реализация интерфейса будет выглядеть следующим образом (источник C++)
#include "MyClass.h"
extern "C"
{
HMyClass * myStruct_create( const char * s )
{
return reinterpret_cast<HMyClass*>( new MyClass( s ) );
}
void myStruct_destroy( HMyClass * v )
{
delete reinterpret_cast<MyClass*>(v);
}
int myStruct_doSomething( HMyClass * v, int i )
{
return reinterpret_cast<MyClass*>(v)->doSomething(i);
}
}
Мы извлекаем наш непрозрачный дескриптор из исходного класса, чтобы избежать необходимости в литье, и (Это, кажется, не работает с моим текущим комплексом Мы должны сделать дескриптор структурой, так как C не поддерживает классы.
Это дает нам базовый интерфейс C. Если вам нужен более полный пример, показывающий один из способов интеграции обработки исключений, то вы можете попробовать мой код на github: https://gist.github.com/mikeando/5394166
Теперь интересная часть гарантирует, что вы правильно получите все необходимые библиотеки C++, связанные в большую библиотеку. Для gcc (или clang) это означает, что выполняется только заключительная стадия связи с использованием g++.
Виден ли iFrame при загрузке или показан позже? Элементы создаются в другом порядке, который является основой метода setTimeout. Пробовали ли вы время ожидания с высоким значением для установленного тайм-аута?
Попробуйте что-то вроде, по крайней мере, полсекунды, чтобы проверить... IE имеет тенденцию делать вещи в другом порядке, поэтому может потребоваться большое тайм-аут, чтобы заставить его не стрелять, пока рендеринг/краска не завершится:
$(function(){
setTimeout(function() {
var myIFrame = $("#iframeName");
myIFrame.focus();
myIFrame.contents().find('#inputName').focus();
}, 500);
});
-121--4859869- Если поле может быть определено как метка времени, можно использовать следующее:
-121--3527913-ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ОБ ОБНОВЛЕНИИ CURRENT_TIMESTAMP);
Я думаю, что вы можете получить некоторые идеи о направлении и/или, возможно, использовать непосредственно SWIG . Я думаю, что рассмотрение нескольких примеров, по крайней мере, даст вам представление о том, какие вещи следует учитывать при переносе одного API в другой. Упражнение может быть полезным.
SWIG - это средство разработки программного обеспечения, которое соединяет программы, написанные на C и C++, с различными высокоуровневыми языками программирования. SWIG используется с различными типами языков, включая общие языки сценариев, такие как Perl, PHP, Python, Tcl и Ruby. Список поддерживаемых языков также включает языки без сценариев, такие как C #, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), Java, Lua, Modula-3, OCAML, Octave и R. Также несколько интерпретированных и скомпилированных реализаций схемы (Guile, MzScheme, Cheme, Chicken) SWIG чаще всего используется для создания высокоуровневых интерпретируемых или скомпилированных сред программирования, пользовательских интерфейсов и в качестве инструмента для тестирования и прототипирования программного обеспечения C/C + +. SWIG также может экспортировать свое дерево синтаксического анализа в виде XML и Lisp s-выражений. SWIG может свободно использоваться, распространяться и изменяться для коммерческого и некоммерческого использования.
Просто замените концепцию объекта с помощью void *
(часто называют непрозрачным типом в C ориентированных библиотеках) и повторно используйте все, что вы знаете от C ++.
Я думаю, что ответ Майкл Андерсон находится на правильном пути, но мой подход будет другим. Вы должны беспокоиться об одном дополнительных делах: исключения. Исключения не являются частью C ABI, поэтому вы не можете позволить исключениям, когда-либо брошенным в течение кода C ++. Таким образом, ваш заголовок будет выглядеть так:
#ifdef __cplusplus
extern "C"
{
#endif
void * myStruct_create( const char * s );
void myStruct_destroy( void * v );
int myStruct_doSomething( void * v, int i );
#ifdef __cplusplus
}
#endif
и файл вашей обертки .CPP будет выглядеть так:
void * myStruct_create( const char * s ) {
MyStruct * ms = NULL;
try { /* The constructor for std::string may throw */
ms = new MyStruct(s);
} catch (...) {}
return static_cast<void*>( ms );
}
void myStruct_destroy( void * v ) {
MyStruct * ms = static_cast<MyStruct*>(v);
delete ms;
}
int myStruct_doSomething( void * v, int i ) {
MyStruct * ms = static_cast<MyStruct*>(v);
int ret_value = -1; /* Assuming that a negative value means error */
try {
ret_value = ms->doSomething(i);
} catch (...) {}
return ret_value;
}
еще лучше: если вы знаете, что все, что вам нужно как один экземпляр Mystruct, не рискуйте Работа с пустотыми указателями, передаваемыми на ваш API. Сделайте что-то вроде этого вместо этого:
static MyStruct * _ms = NULL;
int myStruct_create( const char * s ) {
int ret_value = -1; /* error */
try { /* The constructor for std::string may throw */
_ms = new MyStruct(s);
ret_value = 0; /* success */
} catch (...) {}
return ret_value;
}
void myStruct_destroy() {
if (_ms != NULL) {
delete _ms;
}
}
int myStruct_doSomething( int i ) {
int ret_value = -1; /* Assuming that a negative value means error */
if (_ms != NULL) {
try {
ret_value = _ms->doSomething(i);
} catch (...) {}
}
return ret_value;
}
Эта API многое безопаснее.
Но, как упомянутое Майкл, связывание может стать довольно сложно.
Надеюсь, это поможет
Нетрудно выставить код C ++ к C, просто используйте шаблон дизайна фасада
, я предполагаю, что ваш код C ++ встроен в библиотеку, все, что вам нужно сделать, это сделать один C модуль в вашей библиотеке C ++ в качестве фасада в вашей библиотеке вместе с чистым файлом заголовка C. Модуль C будет вызывать соответствующие функции C ++
, как только вы выполним, что ваши приложения и библиотека C будут иметь полный доступ к выставленному вами API C API.
, Например, вот образец фасадного модуля
#include <libInterface.h>
#include <objectedOrientedCppStuff.h>
int doObjectOrientedStuff(int *arg1, int arg2, char *arg3) {
Object obj = ObjectFactory->makeCppObj(arg3); // doing object oriented stuff here
obj->doStuff(arg2);
return obj->doMoreStuff(arg1);
}
, который вы затем выставляете эту функцию C в качестве API, и вы можете свободно использовать его, как C Lib без беспокойства в
// file name "libIntrface.h"
extern int doObjectOrientedStuff(int *, int, char*);
, очевидно, это надуманный пример, но это Самый простой способ выдержать библиотеку C ++ к C